【问题标题】:How to recursively traverse nested generic collection?如何递归遍历嵌套的泛型集合?
【发布时间】:2014-11-02 16:55:12
【问题描述】:

我想计算嵌套集合中类的数量,例如[[[1,2],[3,4,5]],[[1,2],[3,4,5]]]。这里引用的类是“int”,预期答案是 10。

我将此列表生成为:

        List<int> list1 = new List<int>(2);
        list1.Add(1);
        list1.Add(2);
        List<int> list2 = new List<int>(3);
        list2.Add(3);
        list2.Add(4);
        list2.Add(5);

        List<List<int>> listlist = new List<List<int>>(2);
        listlist.Add(list1);
        listlist.Add(list2);

        List<List<List<int>>> listlistlist = new List<List<List<int>>>(2);
        listlistlist.Add(listlist);
        listlistlist.Add(listlist);

当我在编程时,我更喜欢为泛型类编写这样的方法,我的代码是:

    public static int CountT<T>(ICollection<T> pTCol, int intLevel = 1)
    {
        int intCount = 0;
        if (intLevel > 0)
        {
            intLevel--;
            foreach (T pT in pTCol)
            {
                ICollection<T> subTCol = pT as ICollection<T>;   //PROBLEM: I got "null" for subTCol when the program was running
                intCount += CountT(subTCol, intLevel);
            }
        }
        else if (intLevel == 0)
        {
            intCount = pTCol.Count;
        }
        return intCount;
    }

我测试了上面的代码

        int intCount = CountT(listlistlist, 2);

那么问题来了

        ICollection<T> subTCol = pT as ICollection<T>;   //PROBLEM: I got "null" for subTCol when the program was running

我也试过代码:

    public static int CountT2<T, T2>(ICollection<T> pTCol, int intLevel = 1)
    {
        int intCount = 0;
        if (intLevel > 0)
        {
            intLevel--;
            foreach (T pT in pTCol)
            {
                ICollection<T2> subTCol = pT as ICollection<T2>;
                intCount += CountT2(subTCol, intLevel);   //PROBLEM: The type arguments for method cannot be inferred from the usage. Try specifying the type arguments explicitly. (I could not pass the compiling)
            }
        }
        else if (intLevel == 0)
        {
            intCount = pTCol.Count;
        }
        return intCount;
    }

编译不通过

        intCount += CountT2(subTCol, intLevel);   //PROBLEM: The type arguments for method cannot be inferred from the usage. Try specifying the type arguments explicitly. (I could not pass the compiling)

我该怎么做?

【问题讨论】:

  • 你会一直有三个级别,还是一个任意数字?
  • 在我的实际问题中我只有两个级别,但是我想实现一个泛型的方法,即我想要一个可以处理任意多个级别的方法。
  • 我建议对于任意数量的级别,适当的数据结构是一个,其算法要简单得多。
  • tree 是指像SortedSet 这样的基于树的类吗?在我的问题中,我看不到 tree 的优势。能否举例说明一下优势?

标签: c# .net generics recursion icollection


【解决方案1】:

ICollection subTCol = pT as ICollection //问题:subTCol 得到“null”

这个为空的原因是pT 不是ICollection&lt;T&gt;,因为TintlistlistlistList&lt;List&lt;List&lt;T&gt;&gt;&gt;。因此pTList&lt;List&lt;T&gt;&gt;,这就是为什么如果你尝试将它转换为ICollection&lt;T&gt; 你会得到null。

我想计算嵌套集合中的项目数。

您可以使用Sum 方法更轻松地做到这一点。如果您知道嵌套级别,例如:

Assert.AreEqual(10, listlistlist.Sum(x => x.Sum(y => y.Count)));

如果您不知道嵌套级别或者您想要更通用的方法,您可以创建一个扩展方法,例如:

public static class RecursiveSumExtension
{
    public static int RecursiveSum(this IEnumerable items)
    {
        if (null == items)
            return 0;

        var total = 0;

        foreach (var item in items)
        {
            if (item is IEnumerable)
                total += (item as IEnumerable).RecursiveSum();

            else
                total++;
        }

        return total;
    }
}

和测试:

 Assert.AreEqual(10, listlistlist.RecursiveSum());

列表生成

顺便说一句,您可以在创建集合时使用 的集合初始化语法使代码更具可读性:

        var listlist = new List<List<int>>
        {
            new List<int> {1, 2},
            new List<int> {3, 4, 5}
        };

        var listlistlist = new List<List<List<int>>>
        {
            listlist,
            listlist
        };

【讨论】:

  • 如果我想使用IEnumerable,我需要在类的顶部添加using System.Collections;
猜你喜欢
  • 2021-09-19
  • 1970-01-01
  • 2017-08-19
  • 1970-01-01
  • 2015-11-27
  • 2020-05-20
  • 1970-01-01
  • 2011-09-08
  • 2020-07-20
相关资源
最近更新 更多