簡體   English   中英

如何使用擴展方法或Linq做到這一點?

[英]How can i do this with Extensions methods or Linq?

用我可憐的英語很難解釋,但是我會盡力的。

在下面的列表序列中,如果一個項目的第一個字段與另一個項目的第一個字段具有相同的值,但沒有相同的第二個字段。 結果,我想收集具有相同第一字段但沒有第二字段的項目。

它看起來很簡單,但我認為沒有什么。考慮到您將按相同的順序進行工作,因此有效地執行此操作很重要。

class MyClass
{
    public int first;
    public int second;
}
List<MyClass> sequence = new List<MyClass>();

嘗試這個:

List<MyClass> sequence = new List<MyClass>()
{
    new MyClass{ First = 1, Second = 10 },
    new MyClass{ First = 1, Second = 10 },
    new MyClass{ First = 2, Second = 11 },
    new MyClass{ First = 2, Second = 12 }
};

var doesntMatch = sequence
    .GroupBy(i => i.First)
    .Select(g => new
        { 
            Key = g.Key, 
            Values = g.Select(i => i.Second).Distinct()
        })
    .Where(i => i.Values.Count() > 1);
foreach (var i in doesntMatch)
{
    Console.WriteLine(
        "First = {0} contains {1} distinct values: {2}", i.Key, i.Values.Count(),
        String.Join(", ", i.Values.Select(n => n.ToString()).ToArray()));
}

// output: "First = 2 contains 2 distinct values: 11, 12"

我在想您可能要使用GroupBy。

var sequence = new List<MyClass>() 
{
    new MyClass() { First = 1, Second = 2 },
    new MyClass() { First = 1, Second = 3 },
    new MyClass() { First = 1, Second = 4 },
    new MyClass() { First = 3, Second = 2 },
    new MyClass() { First = 5, Second = 4 },
};

var group1 = sequence.GroupBy(x => x.First);

您可以使用linq進行類似的操作,假設您的MyClass對象處於某種集合中

讓我們說一個list<MyClass> myList作為例子

     (from o in myList where 
(from o1 in myList where o1.first == o.first select o1).Count == 2 
&& (from o2 in  myList where o2.second == o.second select o2).count == 1 
    select o)

這就是說獲取我列表中的所有對象,其中至少有兩個具有第一個參數的對象(o和一些其他對象),只有一個具有第二個參數的對象。

我相信這可以改善。

這是我想出的:

class MyClass
{
    public int First;
    public int Second;
}

void Main()
{ 
    List<MyClass> sequence = new List<MyClass>()
    {
        new MyClass{ First = 1, Second = 10 },
        new MyClass{ First = 1, Second = 10 },
        new MyClass{ First = 1, Second = 11 },
        new MyClass{ First = 2, Second = 11 },
        new MyClass{ First = 2, Second = 12 },
        new MyClass{ First = 3, Second = 10 }
    };

    var lonelyItems = sequence

        // remove all those which don't match First
        .GroupBy(x => x.First).Where(g => g.Count() > 1)

        // keep only one for each Second
        .SelectMany(g => g.GroupBy(x => x.Second)).Select(g => g.First()); 

    foreach (var x in lonelyItems)
        Console.WriteLine(x);

    // output:
    // 1,10
    // 1,11
    // 2,11
    // 2,12
}

我認為您可以通過在first字段相等的情況下將序列與其自身連接來實現此目的。 下面是一些執行此操作的示例代碼。 輸出也如下所示。 請注意,此代碼導致找到重復的匹配項,因此您可能必須解決該問題。

class Program
{
    class MyClass
    {
        public int ID;
        public int first;
        public int second;
    }

    static void Main(string[] args)
    {
        // create a sequence containing example data
        List<MyClass> sequence = new List<MyClass>();
        sequence.AddRange(new MyClass[] {
            new MyClass { ID = 1, first = 0, second = 10 },
            new MyClass { ID = 2, first = 1, second = 11 },
            new MyClass { ID = 3, first = 2, second = 12 },
            new MyClass { ID = 4, first = 0, second = 10 },
            new MyClass { ID = 5, first = 1, second = 20 },
            new MyClass { ID = 6, first = 2, second = 30 },
            new MyClass { ID = 7, first = 0, second = 0 },
            new MyClass { ID = 8, first = 1, second = 11 },
            new MyClass { ID = 9, first = 2, second = 12 },
        });

        var matches = from x in sequence
                      join y in sequence // join sequence to itself
                      on x.first equals y.first // based on the first field
                      where
                        !object.ReferenceEquals(x, y) // avoid matching an item to itself
                        && x.second != y.second // find cases where the second field is not equal
                      select new { X = x, Y = y }; // return a "tuple" containing the identified items

        foreach (var match in matches)
        {
            Console.WriteLine("Found first:{0}, x.second:{1}, y.second:{2}, x.ID:{3}, y.ID:{4}", match.X.first, match.X.second, match.Y.second, match.X.ID, match.Y.ID);
        }
    }
}

該程序的輸出如下:

找到first:0,x.second:10,y.second:0,x.ID:1,y.ID:7

找到first:1,x.second:11,y.second:20,x.ID:2,y.ID:5

找到first:2,x.second:12,y.second:30,x.ID:3,y.ID:6

找到first:0,x.second:10,y.second:0,x.ID:4,y.ID:7

找到first:1,x.second:20,y.second:11,x.ID:5,y.ID:2

找到first:1,x.second:20,y.second:11,x.ID:5,y.ID:8

找到first:2,x.second:30,y.second:12,x.ID:6,y.ID:3

找到first:2,x.second:30,y.second:12,x.ID:6,y.ID:9

找到first:0,x.second:0,y.second:10,x.ID:7,y.ID:1

找到first:0,x.second:0,y.second:10,x.ID:7,y.ID:4

找到first:1,x.second:11,y.second:20,x.ID:8,y.ID:5

找到first:2,x.second:12,y.second:30,x.ID:9,y.ID:6

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM