c#在List中计算连续的重复项

本文关键字:连续 计算 List string | 更新日期: 2023-09-27 18:18:56

我有一个字符串列表,并希望计算其中的重复项,以便稍后使用此信息。简单地计算重复的次数是很容易的,但不幸的是,我只想计算连续的重复次数。

假设我们有一个包含以下字符串items的列表:

"1","3 b","5 x","7问","2 w","2 g","2 j"、"1"、"2"

现在我要计算这个列表中的重复项。我只会看每个字符串的第一个字符,字符串中的其他字符可以忽略!我们得到的是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++;
    }
}

我猜你可以想象这段代码是一种非常丑陋的方式,特别是如果你想要处理输出。我的代码也不能处理我需要的功能。

我要找的代码,必须能够处理我要实现的两个功能。首先,如果列表的最后一个元素等于列表的第一个元素,那么一行重复项就不会结束。

例如:

"1","1 b","5 x","7问","2 j","我"

"1%"必须被检测为重复,因为"1I"answers"1A"是"一行"。如果循环遍历列表,如果第一个元素和最后一个元素不相等,则在列表末尾断开。

伪代码:

if(list.First()[0] != list.Last()[0])

我想实现的第二个特性是,列表中不重复的项,"重复计数"超过4的项将被删除。如果没有一个单一的重复行"复制"或长度超过4我想回报。

例如:

"1","1 b","5 x","3 q"、"1 j","我"

duplicate count == 4 so return

"1","1 b","1 x","3 q"、"1 j","我"

复制count == 5,保存这五个项目,删除列表中的任何其他项目。

"1","1 b","1 x","3 q"、"我"、"z 1","1 z"

duplicate count == 6,保存这6项,删除列表中任何其他项。

注意:每个字符串的第一个字符很重要。输入列表将有7个项目,没有一个项目多或少。没有结果列表,旧的需要更新。如果重复计数小于或等于4,则不需要做任何工作,只需返回即可。在一行中不会有超过5个重复。我必须检查十亿的列表,所以性能真的很重要

由于德国学校没有更好的英语教学,我希望任何人都能理解我的问题所在,并愿意帮助我。

这不是任何家庭作业的一部分。

c#在List<string>中计算连续的重复项

在满足条件的情况下,可以使用一个方法对连续的项进行分组:

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(),
    });

我建议您将列表中以相同字符开头的项分组。这个分组的结果将是一个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();