如何在列表中找到子列表的索引?

Luk*_*beš 9 .net c#

我正在寻找一些有效的方法(在.NET中),如何查找某些字节列表中是否存在字节序列,以及是否存在第一个启动的索引.

例如,假设我有:

var sequence = new List<byte> { 5, 10, 2 };
var listOne = new List<byte> { 1, 3, 10, 5, 10, 2, 8, 9 };
var listTwo = new List<byte> { 1, 3, 10, 5, 2, 10, 8, 9 };
Run Code Online (Sandbox Code Playgroud)

结果应该是我的序列在listOne中的索引3和listTwo中的索引-1(即它不存在)上.

当然,我可以通过int和每个索引循环遍历列表int并搜索以下数字是否与我的序列匹配,但是是否有一些更有效的方法(例如使用扩展方法)?

Jon*_*nna 6

这与子字符串搜索基本上是相同的问题(实际上,顺序有效的列表是"字符串"的概括).

幸运的是,计算机科学经常长时间地考虑这个问题,所以你要站在巨人的肩膀上.

看看文献.一些合理的起点是:

http://en.wikipedia.org/wiki/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm

http://en.wikipedia.org/wiki/Boyer%E2%80%93Moore_string_search_algorithm

http://en.wikipedia.org/wiki/Rabin-karp

即使只是维基百科文章中的伪代码也足以轻松移植到C#.查看不同情况下的性能描述,并确定代码最可能遇到的情况.(我正在考虑你所说的搜索键列表中的第一个是简短的).


dig*_*All 5

我认为最干净的方法是创建这样的通用扩展方法:

public static int SubListIndex<T>(this IList<T> list, int start, IList<T> sublist)
{
    for (int listIndex = start; listIndex < list.Count - sublist.Count + 1; listIndex++)
    {
        int count = 0;
        while (count < sublist.Count && sublist[count].Equals(list[listIndex + count]))
            count++;
        if (count == sublist.Count)
            return listIndex;
    }
    return -1;
}
Run Code Online (Sandbox Code Playgroud)

以这种方式打电话:

var indexOne = listOne.SubListIndex(0, sequence);
var indexTwo = listTwo.SubListIndex(0, sequence);
Run Code Online (Sandbox Code Playgroud)

如果您需要搜索更多的子列表出现,PS也可以从给定的索引开始


Chr*_*sBD 1

我建议将每个转换List<int>为 a String,然后使用 进行搜索String.IndexOf(sequence)以确定序列存在的位置或是否存在。

  • 嗯,我真的怀疑这会提高效率,因为您必须从列表创建字符串(需要更多的内存使用和更多的计算)。当然,这会让事情变得更容易,因为您不需要编写搜索子字符串的代码。 (2认同)