我如何使用扩展方法或 Linq 来做到这一点?

发布于 2024-09-08 20:39:17 字数 319 浏览 4 评论 0原文

用我蹩脚的英语解释它有点困难,但我会尝试。

在下面的列表序列中,如果一个项目的第一个字段与另一个项目的第一个字段值具有相同的值,但第二个字段的值不同。因此,我想收集具有相同第一个字段但不具有第二个字段的项目。

它看起来很简单,但我认为并非如此。考虑到您将按照相同的顺序工作,因此有效地完成它很重要。

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

It is a little hard to explain it with my poor english but i will try.

In below list sequence, if a item first field has same value with another item first field value but not same second fields. As result i want to collect items which has same first field but not second fields.

It looks quite easy but i think it is not any.Consider that you will work on same sequence so it is important doing it effectively.

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

骑趴 2024-09-15 20:39:17

试试这个:

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"

Try this:

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"
木槿暧夏七纪年 2024-09-15 20:39:17

我想你可能想使用 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);

I'm thinking you might want to use 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);
夜司空 2024-09-15 20:39:17

假设您的 MyClass 对象位于某种集合中,您可以使用 linq 执行类似的操作

。 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)

这表示获取我的列表中的所有对象,其中至少有 2 个对象具有第一个参数(o 和其他一些对象),并且只有一个对象具有第二个参数。

我相信这可以改进。

you could do something like this with linq assuming you MyClass objects are in some kind of collection

Let's say a list<MyClass> myList for the example

     (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)

This says get all of the objects in my list where there are at least 2 objects that have the first parameter (o and some other object) and only one objects that have the second parameter.

I'm sure this could be improved upon.

兲鉂ぱ嘚淚 2024-09-15 20:39:17

我认为您可以通过在 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);
        }
    }
}

该程序的输出如下:

找到第一个:0,x.第二个:10,y.第二个:0,x.ID:1,y.ID:7

找到第一个:1,x.第二个:11,y。第二:20,x.ID:2,y.ID:5

找到第一:2,x.第二:12,y.第二:30,x.ID:3,y.ID:6

找到第一:0,x。第二:10,y.第二:0,x.ID:4,y.ID:7

找到 第一:1,x.第二:20,y.第二:11,x.ID:5,y.ID:2

找到第一个:1,x.第二个:20,y.第二个:11,x.ID:5,y.ID:8

找到第一个:2,x.第二个:30,y.第二个:12,x.ID:6, y.ID:3

找到第一个:2, x.第二:30, y.第二:12, x.ID:6, y.ID:9

找到第一个:0, x.第二:0, y.第二:10, x.ID:7, y.ID:1

找到第一个:0, x.第二:0, y.第二:10, x.ID:7, y.ID:4

找到第一个:1, x.第二:11, y.第二:20, x.ID:8, y.ID:5

找到第一:2, x.第二:12, y.第二:30, x.ID:9, y.ID:6

I think that you could do this by joining the sequence to itself on the condition that the first field is equal. Below is some example code that does this. The output is also shown below. Note that this code results in duplicate matches found, so you may have to address that.

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);
        }
    }
}

The output of this program is the following:

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

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

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

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

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

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

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

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

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

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

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

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

┾廆蒐ゝ 2024-09-15 20:39:17

这是我想出的:

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
}

Here's what I came up with:

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
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文