我有一个字符串列表,并希望计算其中的重复项,以便稍后处理此信息。简单地计算重复数据将非常容易,但遗憾的是我只想计算连续重复数。
我们假设我们有一个包含此字符串项的列表:
“1A”, “3B”, “5X”, “7Q”, “2W”, “2G”, “2J”, “1A”, “2A”
现在我想计算此列表中的重复项。 我只会查看每个字符串的第一个字符,字符串中的其他字符可以忽略! 我们得到的是 2x“1%”和 3x“2%”,我实际想要的是连续重复,所以我的结果看起来应该是 3x “2%”。必须忽略 2x“1A”,它们不在一行中。 (%=占位符)
我编写了一个循环遍历列表的代码,并将一个字符串与下一个字符串进行比较
int counter = 0;
for (int i = 0; i < list.Count; i++)
{
char first = list[i][0];
if ((i + 1) == list.Count) break;
char second = list[(i + 1)][0];
if (first == second)
{
counter++;
}
}
我猜你可以想象这个代码是一种非常难看的方式,特别是如果你想使用输出。我的代码也无法处理我需要的功能。
我正在寻找的代码,必须能够处理我想要实现的两个功能。首先,如果列表的最后一个元素等于列表的第一个元素,则一行重复项不会结束。
例如:
“1A”, “1B”, “5X”, “7Q”, “2J”, “1I”
“1%”必须被检测为重复,因为“1I”和“1A”是“连续”的。如果你要循环遍历列表,如果第一个和最后一个元素不相等,你就会在列表的末尾分解。
伪代码:
if(list.First()[0] != list.Last()[0])
我要实现的第二个功能是,列表中不重复的项目,“重复计数”超过4将被删除。如果没有一个重复的行具有“重复计数”或长度超过4,我想返回。
例如:
“1A”, “1B”, “5X”, “3Q”, “1J”, “1I”
重复计数== 4所以返回
“1A”, “1B”, “1X”, “3Q”, “1J”, “1I”
重复count == 5
,保存这五项,删除列表中的任何其他项目。
“1A”, “1B”, “1X”, “3Q”, “1I”, “1Z”, “1Z”
重复计数== 6,保存这六项,删除列表中的任何其他项目。
注意: 只是每个字符串的第一个字符很重要。输入列表将包含7个项目,而不是单个项目或多或少。没有结果列表,旧的必须更新。如果重复计数小于或等于4,则无需做任何工作,只需返回即可。 连续不会超过5个重复。我必须检查十亿个列表,因此性能非常重要
由于他们没有在德国学校教过更好的英语,我希望有人能理解我的问题是什么,并愿意帮助我。
这不是任何家庭作业的一部分。
答案 0 :(得分:2)
这里可以使用的是一种能够在满足条件时对连续项进行分组的方法:
public static IEnumerable<IEnumerable<T>> GroupWhile<T>(
this IEnumerable<T> source, Func<T, T, bool> predicate)
{
using (var iterator = source.GetEnumerator())
{
if (!iterator.MoveNext())
yield break;
List<T> list = new List<T>() { iterator.Current };
T previous = iterator.Current;
while (iterator.MoveNext())
{
if (!predicate(previous, iterator.Current))
{
yield return list;
list = new List<T>();
}
list.Add(iterator.Current);
previous = iterator.Current;
}
yield return list;
}
}
一旦我们有了这个帮助方法,我们就可以用一个相当直接的庄园来编写你的查询:
var query = data.GroupWhile((prev, current) => prev[0] == current[0])
.Where(group => group.Count() > 1)
.Select(group => new
{
Character = group.First()[0],
Count = group.Count(),
});
答案 1 :(得分:0)
我建议你将列表中以相同字符开头的项目分组。此分组的结果将是List<List<string>>
。这样可以更轻松地使用组。
var list = new List<string> {
"1A", "3B", "5X", "7Q", "2W", "2G", "2J", "1B", "1C", "1D", "1E"
};
var groups = new List<List<string>>();
char lastChar = (char)0; // We assume that NUL will never be used as first char.
List<string> group = null;
foreach (string s in list) {
if (s[0] != lastChar) {
group = new List<string>();
groups.Add(group);
lastChar = s[0];
}
group.Add(s);
}
// Join the first and the last group if their first char is equal
int lastIndex = groups.Count - 1;
if (groups.Count > 2 && groups[0][0][0] == groups[lastIndex][0][0]) {
// Insert the elements of the last group to the first group
groups[0].InsertRange(0, groups[lastIndex]);
// and delete the last group
groups.RemoveAt(lastIndex);
}
//TODO: Remove test
foreach (List<string> g in groups) {
Console.WriteLine(g[0][0]);
foreach (string s in g) {
Console.WriteLine(" " + s);
}
}
// Now create a list with items of groups having more than 4 duplicates
var result = new List<string>();
foreach (List<string> g in groups) {
if (g.Count > 4) {
result.AddRange(g);
}
}
//TODO: Remove test
Console.WriteLine("--------");
foreach (string s in result) {
Console.Write(s);
Console.Write(" ");
}
Console.WriteLine();
Console.ReadKey();