C#:与包含列表的区别

发布于 2025-01-07 13:47:31 字数 2553 浏览 0 评论 0原文

我有一个类的实例列表。每个实例都包含一个 IList 属性和一个自定义类的对象。现在我想删除此列表中的所有离散实例,其中包含的 IList-Property 和 MyMulti-Class 的 Multi-Property 的元素是相等的。我只想保留列表中的一个元素,其中“someData”属性的“First”属性最低。 我的建议是,通过包含 IList 属性和“SomeData”属性的“Multi”属性对列表的元素进行分组,然后按“SomeData”属性的“First”属性和选择每组的第一个元素。

我需要它尽可能高性能。有人有什么想法吗?

示例:

class myClass
{
    public IList<String> SomeStrings { get; set; }
    public MyMulti SomeData { get; set; }

    public myClass(MyMulti data, params string[] strings)
    {
        SomeData = data;
        SomeStrings = strings;
    }
}

class MyMulti
{
    public int First { get; set; }
    public int Second { get; set; }

    public int Multi
    {
        get
        {
            return First * Second;
        }
    }

    public MyMulti(int first, int second)
    {
        First = first;
        Second = second;
    }
}
var mc1 = new myClass(new MyMulti(6, 4), "0", "1");
var mc2 = new myClass(new MyMulti(3, 8), "0", "1");
var mc3 = new myClass(new MyMulti(7, 3), "0", "1");
var mc4 = new myClass(new MyMulti(2, 35), "0", "2");
var mc5 = new myClass(new MyMulti(5, 4), "1", "1");
var mc6 = new myClass(new MyMulti(7, 10), "0", "2");

IList<myClass> aList = new List<myClass>(){mc1, mc2, mc3, mc4, mc5, mc6};

var query = aList.GroupBy(x =>
    new
    {
        x.SomeData.Multi,
        x.SomeStrings   
        // don't work cause this will compare the lists 
        // not the containing elements
    })
    .Select(x=>
        x.OrderBy(y=>
            y.SomeData.First)
            .First());

结果应为:mc1 和 mc2 分组然后删除 mc1、mc3 自己的组,mc4 和 mc6 分组然后删除 mc6,mc5 自己的组 --> mc2、mc3、mc4、mc5 应保留

编辑:

如果我首先按 MyClass.SomeData.First 属性对列表进行排序,然后使用 List.Distinct() 方法和自定义 IEqalityComparer 实现,我将得到我正在搜索的内容为了。但这是最有效的方法吗?

public class myClassEqualityComparer : IEqualityComparer<myClass>
{

    public bool Equals(myClass x, myClass y)
    {
        if (!x.SomeData.Multi.Equals(y.SomeData.Multi))
            return false;
        else
            if (x.SomeStrings.AsEnumerable()
                   .SequenceEqual(y.SomeStrings.AsEnumerable()))
                return true;
        return false;
    }

    public int GetHashCode(myClass obj)
    {
        int hCode = obj.SomeData.Multi;
        foreach (var item in obj.SomeStrings)
        {
            hCode = hCode ^ item.GetHashCode();
        }
        return hCode.GetHashCode();
    }
}

I have a List of instances of a class. Each instance contains a IList-property and a object of a custom class. Now I want to drop all distict instances in this List, where the elements of the containing IList-Property and the Multi-Property of the MyMulti-Class are equal. I want to remain only the one element in the List, where the "First"-property of the "someData"-Property is the lowest.
My suggestion was, to group the elements of the List by the containing IList-Property and the "Multi"-property of the "SomeData"-property and then sort it by the "First"-property of the "SomeData"-Property and select the first Element of each group.

I need it as performant as possible. Anyone any ideas?

Example:

class myClass
{
    public IList<String> SomeStrings { get; set; }
    public MyMulti SomeData { get; set; }

    public myClass(MyMulti data, params string[] strings)
    {
        SomeData = data;
        SomeStrings = strings;
    }
}

class MyMulti
{
    public int First { get; set; }
    public int Second { get; set; }

    public int Multi
    {
        get
        {
            return First * Second;
        }
    }

    public MyMulti(int first, int second)
    {
        First = first;
        Second = second;
    }
}
var mc1 = new myClass(new MyMulti(6, 4), "0", "1");
var mc2 = new myClass(new MyMulti(3, 8), "0", "1");
var mc3 = new myClass(new MyMulti(7, 3), "0", "1");
var mc4 = new myClass(new MyMulti(2, 35), "0", "2");
var mc5 = new myClass(new MyMulti(5, 4), "1", "1");
var mc6 = new myClass(new MyMulti(7, 10), "0", "2");

IList<myClass> aList = new List<myClass>(){mc1, mc2, mc3, mc4, mc5, mc6};

var query = aList.GroupBy(x =>
    new
    {
        x.SomeData.Multi,
        x.SomeStrings   
        // don't work cause this will compare the lists 
        // not the containing elements
    })
    .Select(x=>
        x.OrderBy(y=>
            y.SomeData.First)
            .First());

Result should be: mc1 and mc2 grouped and then drop mc1, mc3 own group, mc4 and mc6 grouped and then mc6 droped, mc5 own group --> mc2, mc3, mc4, mc5 should remain

EDIT:

If I first sort the List by the MyClass.SomeData.First-property and then use the List.Distinct()-method and a custom IEqalityComparer implementiation I get, what I'm searching for. But is this the most performant way to do this?

public class myClassEqualityComparer : IEqualityComparer<myClass>
{

    public bool Equals(myClass x, myClass y)
    {
        if (!x.SomeData.Multi.Equals(y.SomeData.Multi))
            return false;
        else
            if (x.SomeStrings.AsEnumerable()
                   .SequenceEqual(y.SomeStrings.AsEnumerable()))
                return true;
        return false;
    }

    public int GetHashCode(myClass obj)
    {
        int hCode = obj.SomeData.Multi;
        foreach (var item in obj.SomeStrings)
        {
            hCode = hCode ^ item.GetHashCode();
        }
        return hCode.GetHashCode();
    }
}

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

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

发布评论

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

评论(2

但可醉心 2025-01-14 13:47:31

为什么不尝试 Distinct() 方法可能会完成你的工作

<代码>List.Distinct();

why dont you try Distinct() method might do your wrok

List.Distinct();

薄凉少年不暖心 2025-01-14 13:47:31

GetHashCode 函数可能会减慢速度。
哈希码用于平衡哈希表,为了获得最佳性能,哈希函数必须为所有输入生成随机分布。您应该尝试:

public int GetHashCode(myClass obj)
{
    return obj.SomeData.First ^ obj.SomeData.Second;
}

您可以使用 System.Diagnostics.Stopwatch 测试性能并循环 100000 到 1000000 次。

you GetHashCode function may slow thing down.
Hash code is used to balance hash table and for the best performance, a hash function must generate a random distribution for all input. You should try:

public int GetHashCode(myClass obj)
{
    return obj.SomeData.First ^ obj.SomeData.Second;
}

You may test performance using System.Diagnostics.Stopwatch and loop 100000 to 1000000 times.

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