gpt4 book ai didi

c# - 如何使用 LINQ 实现此目的?

转载 作者:太空狗 更新时间:2023-10-29 22:21:15 24 4
gpt4 key购买 nike

我能描述我正在尝试做的事情的最好方式是“Nested DistinctBy”。

假设我有一组对象。每个对象都包含一组昵称。

class Person
{
public string Name { get; set; }
public int Priority { get; set; }
public string[] Nicknames { get; set; }
}

public class Program
{
public static void Main()
{
var People = new List<Person>
{
new Person { Name = "Steve", Priority = 4, Nicknames = new string[] { "Stevo", "Lefty", "Slim" }},
new Person { Name = "Karen", Priority = 6, Nicknames = new string[] { "Kary", "Birdie", "Snookie" }},
new Person { Name = "Molly", Priority = 3, Nicknames = new string[] { "Mol", "Lefty", "Dixie" }},
new Person { Name = "Greg", Priority = 5, Nicknames = new string[] { "G-man", "Chubs", "Skippy" }}
};
}
}

我想选择所有人物,但要确保没有人与其他人共享昵称。 Molly 和 Steve 都有一个昵称“左撇子”,所以我想过滤掉其中一个。只应包括具有最高优先级的那个。如果 2 个或更多之间存在最高优先级的关系,则只需选择其中的第一个。所以在这个例子中,我想要一个 IEnumerable,包含除了 Steve 之外的所有人。

编辑:这是另一个使用音乐专辑而不是人物的例子,可能更有意义。

class Album
{
string Name {get; set;}
int Priority {get;set;}
string[] Aliases {get; set;}
{

class Program
{
var NeilYoungAlbums = new List<Album>
{
new Person{ Name = "Harvest (Remastered)", Priority = 4, Aliases = new string[] { "Harvest (1972)", "Harvest (2012)"}},
new Person{ Name = "On The Beach", Priority = 6, Aliases = new string[] { "The Beach Album", "On The Beach (1974)"}},
new Person{ Name = "Harvest", Priority = 3, Aliases = new string[] { "Harvest (1972)"}},
new Person{ Name = "Freedom", Priority = 5, Aliases = new string[] { "Freedom (1989)"}}
};
}

这里的想法是我们想展示他的唱片目录,但我们想跳过准重复。

最佳答案

我会使用自定义 IEqualityComparer<T> 来解决这个问题:

class Person
{
public string Name { get; set; }

public int Priority { get; set; }

public string[] Nicknames { get; set; }
}

class PersonEqualityComparer : IEqualityComparer<Person>
{
public bool Equals(Person x, Person y)
{
if (x == null || y == null) return false;

return x.Nicknames.Any(i => y.Nicknames.Any(j => i == j));
}

// This is bad for performance, but if performance is not a
// concern, it allows for more readability of the LINQ below
// However you should check the Edit, if you want a truely
// LINQ only solution, without a wonky implementation of GetHashCode
public int GetHashCode(Person obj) => 0;
}

// ...

var people = new List<Person>
{
new Person { Name = "Steve", Priority = 4, Nicknames = new[] { "Stevo", "Lefty", "Slim" } },
new Person { Name = "Karen", Priority = 6, Nicknames = new[] { "Kary", "Birdie", "Snookie" } },
new Person { Name = "Molly", Priority = 3, Nicknames = new[] { "Mol", "Lefty", "Dixie" } },
new Person { Name = "Greg", Priority = 5, Nicknames = new[] { "G-man", "Chubs", "Skippy" } }
};

var distinctPeople = people.OrderBy(i => i.Priority).Distinct(new PersonEqualityComparer());

编辑:

为了完整起见,这可能是一种可能的仅 LINQ 方法:

var personNicknames = people.SelectMany(person => person.Nicknames
.Select(nickname => new { person, nickname }));
var groupedPersonNicknames = personNicknames.GroupBy(i => i.nickname);
var duplicatePeople = groupedPersonNicknames.SelectMany(i =>
i.OrderBy(j => j.person.Priority)
.Skip(1).Select(j => j.person)
);

var distinctPeople = people.Except(duplicatePeople);

关于c# - 如何使用 LINQ 实现此目的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56920369/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com