C#嵌套列出GroupBy列表而不是值

时间:2014-01-20 20:51:58

标签: c# linq list nested

我有一个名为“fnc”的2D列表(嵌套列表),我想删除重复项并使用LINQ在富文本框中显示。我试过“groupby”但它没有用。我怎样才能做到这一点?谢谢你的帮助。

var grptest = fnc.GroupBy(x=>x);
foreach (var sublist in grptest)
{
    foreach (var value in sublist)
    {
        ResultRTB.AppendText(value.ToString());
    }
}

我在

中有这些值
fnc = ((C1,C2,C3),(C2),(C1,C3),(C1,C3),(C1,C2,C3),(C3)) 

我想删除重复的结果将是

fnc = ((C1,C2,C3),(C2),(C1,C3),(C3)) 

2 个答案:

答案 0 :(得分:2)

默认GroupBy()和Distinct()不会执行您想要的操作,因为您正在查找不同的列表,而不是这些列表中的单个值。由于List是引用类型,因此两个列表可能具有相同的元素,但Distinct()仍将返回两个列表。

如果你想(正如你在评论中所说):

  

fnc =((C1,C2,C3),(C2),(C1,C3),(C1,C3),(C1,C2,C3),(C3))我想删除重复的结果将是fnc =((C1,C2,C3),(C2),(C1,C3),(C3))

然后您可以使用Distinct,但提供您自己的Equality Comparer。这要求您重写Equals(表示两个列表中的值相同时)并实现GetHashCode()方法。 GetHashCode()的代码取自here。如果您想了解更多有关您需要Equals和GetHashCode的原因,请参阅here

以下代码的输出为:

Fill
( 1 2 )
( 1 )
( 1 2 )
( 1 )
( 1 2 )
De-dupe
( 1 2 )
( 1 )

代码:

static class Program
{

    class ListEqualityComparer : IEqualityComparer<List<int>>
    {
        public bool Equals( List<int> x, List<int> y )
        {
            return ( x.Count == y.Count ) && new HashSet<int>( x ).SetEquals( y );
        }

        public int GetHashCode( List<int> list )
        {
            int hash = 19;
            foreach( int val in list )
            {
                hash = hash * 31 + val.GetHashCode();
            }
            return hash;
        }
    }
    //Fill is just a method to fill the original lists for testing
    static void Fill( List<List<int>> toFill )
    {
        Console.WriteLine( "Fill" );
        for( int i = 1; i <= 5; i++ )
        {
            Console.Write( "( " );
            List<int> newList = new List<int>();
            toFill.Add(newList);
            for( int j = 1; j <= i%2 + 1; j++ )
            {
                newList.Add( j );
                Console.Write( j + " " );                    
            }
            Console.WriteLine( ")" );
        }
    }
    static void Main( string[] args )
    {
        List<string> result = new List<string>();
        List<List<int>> fnc = new List<List<int>>();
        Fill( fnc );
        var results = fnc.Distinct( new ListEqualityComparer() );
        Console.WriteLine( "De-dupe" );
        foreach( var list in results )
        {
            Console.Write( "( " );
            foreach( var element in list )
            {
                Console.Write( element + " " );
            }
            Console.WriteLine( ")" );
        }
    }
}

答案 1 :(得分:1)

我将基于您的评论假设您正在使用字符串,因为您没有真正指定其他方式。列表是对象,因此它们具有引用。所以在下面的例子中,

var fnc = new List<List<string>>
    {
        new List<string>{"a", "b", "c"},
        new List<string>{"a", "b", "c"}
    };

var groupedFnc = fnc.GroupBy(x => x);
var distinctFnc = fnc.Distinct();

GroupByDistinct的调用不会对列表执行任何操作,因为每个列表的引用确实已经是唯一的。在这种情况下你需要做的是写一个自定义函数传递给组,它会遍历列表并识别哪个内部列表是这个列表的重复。

另一个替代方法是编写自定义比较器类并覆盖EqualsGetHashCode实现并提供自己的实现,以便在执行GroupBy操作时,引用不是导致重复的部分不被识别。有关如何执行此操作的更多信息:

How to group by on a reference type property in linq?