我有一个对象列表:
例如A, A, B, C, D, E, E
我已经定义了模板,告诉我们如何对对象类型进行分组 例如
Group Alpha --> A 1..n --> any number of 'A's can be grouped
Group Charlie --> Sequences of 'BCD' can be grouped
Group Epsilon --> E 1..n --> any number of 'E's can be grouped
现在我想在原始列表中应用这些组定义,这应该给出结果:
Group Alpha (2x'A'), Group Charlie (1x'BCD'), Group Epsilon (2x'E')
如何才能最好地实现这一目标?我的问题是否有已知的搜索算法/模式? 我尝试了一种非常基本的方法,在列表上循环多次,并试图从每个列表条目和匹配模式中向前看,但由于复杂性而完全丢失...
提前感谢任何暗示!!!
答案 0 :(得分:2)
这是一个修改过的字符串匹配问题。您有两种类型的输入:
像“BCD”这样的人。如果您只有这个,可以使用任何传统算法here
一行中相同对象的任意数量。
我脑子里有两种解决方案:
使用传统的字符串算法(KMP或其他),但为第二种输入类型制定例外规则。
建立如:
上面的数字很糟糕。如果您有任何问题,请告诉我。
答案 1 :(得分:2)
我不完全确定这是你需要的,但是用这个小代码我可以创建你指定的输出
简单用法(带断言):
var a1 = new List<string> { "A", "A", "B", "C", "D", "E", "E" };
a1.ApplyCriteria("A").Criteria.Should().Be("A");
a1.ApplyCriteria("A").Count.Should().Be(2);
a1.ApplyCriteria("E").Criteria.Should().Be("E");
a1.ApplyCriteria("E").Count.Should().Be(2);
a1.ApplyCriteria("BCD").Criteria.Should().Be("BCD");
a1.ApplyCriteria("BCD").Count.Should().Be(1);
a1.ApplyCriteria("CD").Criteria.Should().Be("CD");
a1.ApplyCriteria("CD").Count.Should().Be(1);
// not found
a1.ApplyCriteria("CDA").Criteria.Should().Be("CDA");
a1.ApplyCriteria("CDA").Count.Should().Be(0);
ApplyCriteria方法返回的GroupResult类如下所示:
class GroupResult
{
public string Criteria { get; set; }
public int Count { get; set; }
}
这些是正在进行实际工作的扩展方法
static class Ext
{
public static GroupResult ApplyCriteria(this IEnumerable<string> source, string criteria)
{
var elements = source.ToConcatenedString();
return new GroupResult { Criteria = criteria, Count = elements.CountOcurrences(criteria) };
}
public static int CountOcurrences(this string source, string phrase)
{
return source
.Select((c, i) => source.Substring(i))
.Count(sub => sub.StartsWith(phrase));
}
public static string ToConcatenedString<TSource>(this IEnumerable<TSource> source)
{
var sb = new StringBuilder();
foreach (var value in source)
{
sb.Append(value);
}
return sb.ToString();
}
}
答案 2 :(得分:1)
假设您有某种代码可以在对象之间进行比较,并告诉A和什么是B,您可以将模板定义为数组,然后遍历原始列表,搜索模板&#39; s出现次数。
CustomObj[] template = new CustomObj[]{B,C,D};
for (int i=0; i< originalList.Length- template.Length + 1; i++)
{
bool found= true;
for(int j=0; j< template.Length;j++)
{
found = template[j] == originalList[i +j];
}
if (found)
{
//add to results list
}
}
搜索比较算法(其中最简单的,据我记得)使用这些概念,还有一些压缩算法,但它们从另一方面开始工作(构建模板以通过模板的creatinbg索引减少存储)
修改强>
结果我实际上实现了simple Rabin-Karp algorithm
我记得它是这样的:)
答案 3 :(得分:1)
在基础知识中,您可以构建state machine。它将有6个状态,“Init”,“alpha”,“B”,“C”,“charlie”和“epsilon”。
从init开始:
在州aplha:
在州B:
在州C:
在州D:
在州epsilon:
我知道它看起来很复杂,但实际上并非如此,至少在这一点上,特别是如果您创建状态图。当然,如果你想要更通用的东西,或者你想继续添加新的模式,或者你有更多的模式,它会很快变得非常复杂。在这种情况下,我认为你的最佳镜头是string matching algorithms中的一个适应你的问题。