【问题标题】:Best way to find how many times an item in a list repeats in a row, in C#? [closed]在 C# 中查找列表中的项目连续重复多少次的最佳方法? [关闭]
【发布时间】:2019-11-20 21:08:06
【问题描述】:

给定一个列表,例如: List<int> _ = new List<int>() { 1, 1, 1, 3, 3, 4, 4, 1, 1, 8, 8, 8, 5, 6, 7, 7, 7, 7, 8, 8 };

在 C# 中,查找一个项目连续重复多少次的最佳/最快/最有效方法是什么? 对于这个列表,我要寻找的结果是这样的:

1 * 3

3 * 2

4 * 2

1 * 2

8 * 3

5 * 1

6 * 1

7 * 4

8 * 2

不一定非得是这种奇数乘法格式,我觉得这样比较容易理解。

我一直在尝试循环遍历列表并将每个项目与下一个项目进行比较,但我不可避免地会卡住,并且不知道该怎么做。

【问题讨论】:

  • 尝试在整个集合中循环执行。 List<int> 将数字用作索引,否则会向上计数。或者Dictionary<int, int> 可以轻松做到这一点。
  • 请看在你所珍视的一切的份上,不要只命名变量_
  • 所以你已经实例化了列表......你在哪里尝试迭代和跟踪计数?你能在代码的那部分edit 吗?
  • 向我们展示您的循环尝试,以便我们修复它。
  • 您要求“最佳”、“最快”和“最有效”,但这些不一定是同一回事。给出一个可以衡量“最佳”和“效率”的指标,并记住我们经常用更差的内存使用来换取更快的速度。

标签: c# list iteration


【解决方案1】:

我会遍历列表,对于每个项目,我会查看当前项目是否与前一个项目相同。如果是,则增加一个计数变量并继续。如果不是,则捕获上一项和计数并将上一项重置为当前项并将计数重置为1

使这更容易的一种方法是创建一个包含ValueCount 的简单类,以便我们可以返回代表列表中项目的这些列表:

public class Item<T>
{
    public T Value { get; set; }
    public int Count  { get; set; }

    public override string ToString()
    {
        return $"{Value} * {Count}";
    }
}

然后我们可以编写一个泛型方法,它接受一个列表并返回上面类的列表,使用开头提到的策略:

public static List<Item<T>> GetItemCounts<T>(List<T> input)
{
    if (input == null) return null;
    var itemCounts = new List<Item<T>>();
    Item<T> currentItem = null;

    foreach (var item in input)
    {
        // If we haven't set an item yet, do so
        if (currentItem == null)
        {
            currentItem = new Item<T> {Value = item, Count = 1};
        }
        // If the current item is the same as this item, increment the count
        else if (currentItem.Value.Equals(item))
        {
            currentItem.Count++;
        }
        // This is a new item, so save the current item and create a new one
        else
        {
            itemCounts.Add(currentItem);
            currentItem = new Item<T> { Value = item, Count = 1 };
        }
    }

    // Add the last item
    if (currentItem != null) itemCounts.Add(currentItem);

    return itemCounts;
}

现在,使用您的示例输入,我们可以使用上述方法获得结果:

public static void Main(string[] args)
{
    var items = new List<int> {1, 1, 1, 3, 3, 4, 4, 1, 1, 8, 8, 8, 5, 6, 7, 7, 7, 7, 8, 8};

    // Get our item counts and output them to the console window
    GetItemCounts(items).ForEach(Console.WriteLine);

    GetKeyFromUser("\nDone! Press any key to exit...");
}

输出

【讨论】:

  • 哇。尽管我的措辞平淡无奇,但感谢您的详细解释!这很有帮助!
【解决方案2】:

这是一个有效的算法。

这个想法是这样的;遍历列表,直到我们到达倒数第二个项目,并在每次迭代时查看当前项目是否与下一个项目相同。如果是这样,增加repeat 变量,它被初始化为1。否则,打印当前项目的计数并重置repeat

var numbers = new List<int>() { 1, 1, 1, 3, 3, 4, 4, 1, 1, 8, 8, 8, 5, 6, 7, 7, 7, 7, 8, 8, 7 };

var repeat = 1;
for (int i = 0; i < numbers.Count - 1; i++)
{
    if (numbers[i] == numbers[i + 1])
    {
        repeat++;
    }
    else
    {
        Console.WriteLine("{0} * {1}", numbers[i], repeat);
        repeat = 1;
    }

    if (i == numbers.Count - 2)
    {
        if (numbers[i] == numbers[i + 1])
        {
            Console.WriteLine("{0} * {1}", numbers[i], repeat);
        }
        else
        {
            Console.WriteLine("{0} * {1}", numbers[i + 1], 1);
        }
    }
}

最后附加的if是为了处理最后一项的特殊情况。由于我们只迭代循环直到倒数第二项,我们需要单独检查最后一项。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-08-24
    • 2017-12-18
    • 2011-10-22
    • 2016-07-17
    • 2013-03-31
    • 2016-12-03
    • 1970-01-01
    相关资源
    最近更新 更多