【问题标题】:C# count consecutive duplicates in List<string>C# 计算 List<string> 中的连续重复项
【发布时间】:2017-04-20 18:48:04
【问题描述】:

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

假设我们有一个包含此字符串项的列表:

"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 个重复项。我必须检查十亿个列表,所以性能真的很重要

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

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

【问题讨论】:

  • 你实际上并没有问过问题。
  • “in a row”实际上是指连续重复?
  • 什么是更改我的代码或提供任何输入您将如何解决问题的最佳方法;)“连续”我的意思是连续的,是的。

标签: c# performance list duplicates


【解决方案1】:

您可以在此处使用一种能够在满足条件时对连续项目进行分组的方法:

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

【讨论】:

  • 我不能像 var query = list.GroupWhile((prev, current) => prev[0] == current[0]) .Where(group => group.Count() > 1) .Select(group => new { Character = group.First()[0], Count = group.Count(), });我想我忽略了显而易见的
  • @user3868224 为什么你不能呢?
【解决方案2】:

我建议您将列表中以相同字符开头的项目分组。此分组的结果将是 List&lt;List&lt;string&gt;&gt;。这样可以更轻松地与小组合作。

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

【讨论】:

  • 小改动对我有用,谢谢!单次运行大约需要 0.00003 - 0.00004 秒,足够快。
猜你喜欢
  • 2014-11-11
  • 1970-01-01
  • 2017-01-13
  • 2022-01-08
  • 2020-01-23
  • 2016-06-11
  • 2017-09-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多