【问题标题】:Divide a single List of Class Objects into multiple Lists based on Class Members C#基于类成员C#将单个类对象列表划分为多个列表
【发布时间】:2017-07-19 00:02:34
【问题描述】:

我有一个 Person 类,如下所示:

public class Person
{
    public Person() { }
    public Person(string name, int age, GenderType gender, string country) { Name = name; Age = age; Gender = gender; Country = country; }

    public string Name { get; set; }
    public int Age { get; set; }
    public GenderType Gender { get; set; } // GenderType = M/F
    public string Country { get; set; }
}

我想先根据性别将此列表分为两个列表。然后我想根据 Country 将每个列表进一步划分为子列表。因此,如果我在原始列表中有 n 个不同的国家/地区,那么最后我会得到 n 到 2n 个列表。下面的例子将进一步说明这个想法:

说我原来的列表是这样的:

Sam, 23, M, USA
Jon, 13, M, USA
Jen, 26, F, USA
Thilini, 25, F, Sri Lanka
Anna, 23, F, UK
Chelsea, 35, F, UK
Saman, 43, M, Sri Lanka
Dan, 27, M, UK

第一师:

Male lists:
Sam, 23, M, USA
Jon, 13, M, USA
Saman, 43, M, Sri Lanka
Dan, 27, M, UK

------------------

Female lists:
Jen, 26, F, USA
Thilini, 25, F, Sri Lanka
Anna, 23, F, UK
Chelsea, 35, F, UK

然后进一步细分列表:

Male sub-list 1:
Sam, 23, M, USA
Jon, 13, M, USA

Male sub-list 2:
Saman, 43, M, Sri Lanka

Male sub-list 3:
Dan, 27, M, UK

------------------

Female sub-list 1:
Jen, 26, F, USA

Female sub-list 2:
Thilini, 25, F, Sri Lanka

Female sub-list 3:
Anna, 23, F, UK
Chelsea, 35, F, UK

我可以很容易地使用 foreach 循环来做到这一点,并可能使用 Results 类来遍历每个项目。但我想了解如何使用 Linq GroupBy() 和 Distinct() 来做到这一点?

我使用 GroupBy() 将其根据 Gender 分为两个列表,如下所示。

static void Main(string[] args)
{
    List<Person> people = new List<Person>()
    {
        new Person("Sam", 23, GenderType.M, "USA"),
        new Person("Jon", 13, GenderType.M, "USA"),
        new Person("Jen", 26, GenderType.F, "USA"),
        new Person("Thilini", 25, GenderType.F, "Sri Lanka"),
        new Person("Anna", 23, GenderType.F, "UK"),
        new Person("Chelsea", 35, GenderType.F, "UK"),
        new Person("Saman", 43, GenderType.M, "Sri Lanka"),
        new Person("Dan", 27, GenderType.M, "UK")
    };

    var maleList = people.GroupBy(x => x.Gender).Where(y => y.Key == GenderType.M);
    var femaleList = people.GroupBy(x => x.Gender).Where(y => y.Key == GenderType.F);

    Console.ReadLine();
}

我不明白现在如何根据国家/地区再次将每个列表细分为多个列表。

【问题讨论】:

  • “我不明白现在如何根据国家/地区将每个列表再细分为多个” -- 为什么不呢?只需将GroupBy() 再次应用于您的每个maleListfemaleList 对象。你有什么不明白的?
  • @PeterDuniho 我知道在我的列表中我只有两个性别类别,所以我可以使用上面的 where 进行分组。但我事先不知道我的列表中可能包含哪些国家/地区,那么我应该使用什么来分组?
  • 你能澄清一下预期的结果吗?列表列表List&lt;List&lt;Person&gt;&gt;?单独列出List&lt;Person&gt;?还是别的什么?
  • @SergeyBerezovskiy 任何一个都可以。

标签: c# list linq group-by distinct


【解决方案1】:

我事先不知道我的列表中可能包含的国家/地区,那么我应该使用什么来分组?

GroupBy() 方法不关心您是否事先知道可能的值是什么。您可以提供任何可相等的键,它会在该键上生成组的枚举。

听起来您需要帮助的不是分组,而是如何表示结果。有很多不同的方法可以做到这一点,所以这个问题可能太宽泛了。但是恕我直言,存储根据键分组的数据的最有用方法之一是在字典中。在您的示例中,它看起来像这样:

static void Main(string[] args)
{
    List<Person> people = new List<Person>()
    {
        new Person("Sam", 23, GenderType.M, "USA"),
        new Person("Jon", 13, GenderType.M, "USA"),
        new Person("Jen", 26, GenderType.F, "USA"),
        new Person("Thilini", 25, GenderType.F, "Sri Lanka"),
        new Person("Anna", 23, GenderType.F, "UK"),
        new Person("Chelsea", 35, GenderType.F, "UK"),
        new Person("Saman", 43, GenderType.M, "Sri Lanka"),
        new Person("Dan", 27, GenderType.M, "UK")
    };

    Dictionary<GenderType, Dictionary<string, List<Person>>> groups =
        people.GroupBy(p => p.Gender).ToDictionary(g => g.Key,
            g1 => g1.GroupBy(p => p.Country).ToDictionary(g2 => g2.Key, g2 => g2.ToList()));

    Console.ReadLine();
}

即与其为每个组设置单独的变量,不如使用一个字典,其中键值为性别,值也是字典,其键值为国家代码。这将使您可以轻松快捷地查找所需的任何性别和国家/地区组合。

【讨论】:

  • 谢谢!我认为这真的是我一直在寻找的——完美地工作。我喜欢字典和消除单独变量的想法。
【解决方案2】:

只需按复合键进行分组:

var groups = people.GroupBy(p => new { p.Gender, p.Country });

然后你可以迭代组并显示结果:

foreach(var group in groups.OrderBy(g => g.Key.Gender).ThenBy(g => g.Key.Country))
{
    Console.WriteLine($"{group.Key.Gender} sub list {group.Key.Country}");

    foreach(var person in group)
        Console.WriteLine($"{person.Name} {person.Age} {person.Gender} {person.Country}");
}

【讨论】:

    猜你喜欢
    • 2011-12-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-27
    • 2019-03-14
    • 1970-01-01
    • 2012-07-01
    • 1970-01-01
    相关资源
    最近更新 更多