将不同的值从列表中分离到不同的列表对象c#

时间:2014-03-21 19:58:11

标签: c# linq list

我有一个列表对象,其中有100个数字。 我想将所有列表对象与所有唯一数字分开。

这是我的列表对象

public class USERDETAILS
{
     private long _ID;
     public long ID
     {
         get { return _ID; }
         set { _ID = value; }
     }

     private long _MSISDN;
     public long MSISDN
     {
         get { return _MSISDN; }
         set { _MSISDN = value; }
     }
}

List<USERDETAILS> lstUSERDETAILS = new List<USERDETAILS>();

我的名单中有10个号码

ID  MSISDN
101 9000001
102 9000002
103 9000002
104 9000003
105 9000003
106 9000003
107 9000007
108 9000008
109 9000009
110 9000010

我希望在不同的列表对象中获得重复的条目。 这是预期的输出:

第一个列表对象:

ID  MSISDN
101 9000001
102 9000002
104 9000003
107 9000007
108 9000008
109 9000009
110 9000010

第二个列表对象:

ID  MSISDN
103 9000002
105 9000003

第三个列表对象:

ID  MSISDN
106 9000003

我试过linq group by;

var listOfUnique_USERDETAILS_Lists = listUSERDETAILS.GroupBy(p => p.MSISDN).Select(g => g.ToList());

此外,我尝试迭代for循环以获取不同的数字,然后将其放在list<USERDETAILS>对象中,然后在新的重复条目列表中创建它,但希望以更简化的方式进行。

2 个答案:

答案 0 :(得分:2)

你走了。

如果你运行:

List<UserDetails> source = new List<UserDetails>();

UserDetails[][] grouping = source
                         .GroupBy( x=> x.MSISDN )
                         .Select( y => y.OrderBy( z => z.ID ).ToArray() )
                         .ToArray()
                         ;

为您提供UserDetails[]

的数组

grouping[n]为您提供所有UserDetails个对象的数组,这些对象共享相同的MSISDN值,按其ID属性排序。

grouping[n][0]将为您提供MSISDN的第一个此类对象。对此进行迭代将会给你带来&#34; distinctified&#34; &#34;第一&#34;对象。由于每个分组都保证至少有一个这样的项目,我们可以简单地说:

UserDetails[] firstList = grouping.Select( x => x.First() ).ToArray() ;

您可以通过以下方式获取第2,第3,第4等列表:

        int n = 2 ; // specify a suitable value for n such that n > 0 (1:1st, 2:2nd, etc.)
        UserDetails[] nthList = grouping.Select( x => x.Skip(n-1).FirstOrDefault() ).Where( x => x != null ).ToArray() ;

注意:由于2d数组是锯齿状的(因此,每个MSISDN可能没有第n个元素,我们使用Skip(n-1).FirstOrDefault().Where( x => x != null )来扔丢失的物品。

更通用的解决方案是采用grouping[][]并*转置其行和列,以使grouping[x][y]变为ranking[y][x]。这样,您就可以将转置后的ranking[][]视为ranking[0]UserDetails[],这是您在所有MSISDN值中排名第一的对象,ranking[0]是您的第二个对所有MSISDN值等的对象进行排名

您可能希望做的不仅仅是简单的换位,因为任何给定的MSISDN可能没有排名第n的项目,因为 n 的任何值都大于0

我相信(未经测试)您可以使用LINQ进行二维转换:

UserDetails[][] ranking = Enumerable
                          .Range( 0 ,grouping.Max(x => x.Length) )
                          .Select( rank => Enumerable
                                           .Range(0,grouping.Length)
                                           .Select( msisdn => grouping[msisdn].Skip(rank-1).FirstOrDefault() )
                                           .Where( x => x != null )
                                           .ToArray()
                          )
                          .ToArray()
                          ;

最后ranking[0]应该是您的第一个列表,ranking[1]是您的第二个列表,ranking[2]是您的第三个列表。

答案 1 :(得分:0)

首先使用GroupBy对项目进行分组,然后您可以迭代这些组并将它们投影到IEnumerator个对象,拉出仍然有项目的组并产生下一个项目,直到没有一个组有任何项目。

//TODO give better name
public static IEnumerable<IEnumerable<T>> Foo<T, TKey>(
    IEnumerable<T> source, Func<T, TKey> selector)
{
    var groups = source.GroupBy(selector)
        .Select(group => group.GetEnumerator())
        .ToList();
    while (groups.Any())
    {
        yield return groups.Select(iterator => iterator.Current);
        groups = groups.Where(iterator => iterator.MoveNext())
            .ToList();
    }
}