我對如何使用 Linq 將串列與兩個串列相關的相同組合進行分組有疑問。
例子:
我有這些課程。
public class PetCategoryOwner
{
public string PetCategory { get; set; }
public string Owner { get; set; }
}
public class PetCategoriesOwners
{
public IEnumerable<string> PetCategories { get; set; }
public IEnumerable<string> Owners { get; set; }
}
示例資料。
| 所有者 | 寵物類別 |
|---|---|
| 比嘉 | 特里 |
| 比嘉 | 夏洛特 |
| 奧利弗 | 特里 |
| 奧利弗 | 夏洛特 |
| 奧利弗 | 喬西 |
| 價格 | 喬西 |
| 利亞姆 | 特里 |
| 利亞姆 | 沙特勒 |
var petCategoryOwner = new List<PetCategoryOwner>()
{
new PetCategoryOwner { Owner = "Higa", PetCategory = "Terry"},
new PetCategoryOwner { Owner = "Higa", PetCategory = "Charlotte"},
new PetCategoryOwner { Owner = "Oliver", PetCategory = "Terry"},
new PetCategoryOwner { Owner = "Oliver", PetCategory = "Charlotte"},
new PetCategoryOwner { Owner = "Oliver", PetCategory = "Chausie"},
new PetCategoryOwner { Owner = "Price", PetCategory = "Chausie"},
new PetCategoryOwner { Owner = "Liam", PetCategory = "Terry"},
new PetCategoryOwner { Owner = "Liam", PetCategory = "Chartreux"}
};
預期值
| 所有者 | 寵物類別 | 團體 |
|---|---|---|
| 比嘉 | 特里 | 一個 |
| 比嘉 | 夏洛特 | 一個 |
| 奧利弗 | 特里 | 一個 |
| 奧利弗 | 夏洛特 | 一個 |
| 奧利弗 | 喬西 | 乙 |
| 價格 | 喬西 | 乙 |
| 利亞姆 | 特里 | C |
| 利亞姆 | 沙特勒 | C |
var petCategoriesOwners = new List<PetCategoriesOwners>()
{
new PetCategoriesOwners()
{
PetCategories = new List<string>() { "Terry", "Charlotte" },
Owners = new List<string>() { "Oliver", "Higa" }
},
new PetCategoriesOwners()
{
PetCategories = new List<string>() { "Chausie" },
Owners = new List<string>() { "Oliver", "Price" }
},
new PetCategoriesOwners()
{
PetCategories = new List<string>() { "Chartreux", "Terry" },
Owners = new List<string>() { "Liam" }
}
}
uj5u.com熱心網友回復:
為了解決您的問題,您需要執行兩個步驟:按所有者分組和基于其他組的集合是當前所有者的子集這一事實合并所有者。您可以嘗試通過運行以下 LINQ 查詢來實作它:
public class PetCategoriesOwners
{
public List<string> PetCategories { get; set; }
public List<string> Owners { get; set; }
}
var petCategoriesOwners = petCategoryOwner
.GroupBy(x => x.Owner)
.Select(x => new
{
Owner = x.Key,
Categories = x.Select(y => y.PetCategory)
})
.OrderBy(x => x.Categories.Count())
.Aggregate(new List<PetCategoriesOwners>(), (acc, current) =>
{
var currentCategories = current.Categories.ToList();
var matches = acc.Where(group => group.PetCategories.All(x => currentCategories.Contains(x)));
foreach(var match in matches)
{
match.Owners.Add(current.Owner);
currentCategories = currentCategories.Except(match.PetCategories).ToList();
}
if (currentCategories.Any())
{
acc.Add(
new PetCategoriesOwners() {
Owners = new List<string>() { current.Owner },
PetCategories = currentCategories
});
}
return acc;
});
因此Owner,根據長度按升序對行程組進行分組很重要。該Aggregate方法主要嘗試查找先前輸入的專案是否與當前處理的專案重疊。如果發生這種情況,那么我們會獲取那些相交的元素,在那里添加所有者并從當前元素中洗掉它們。如果留下任何元素,那么我們為此類所有者創建自己的組。
編輯:.NET 小提琴
uj5u.com熱心網友回復:
注意:此答案基于對問題帖子的錯誤解釋。在其中,我假設這petCategoriesOwners是一個輸入,并且包含該Group列的表的內容是預期的輸出。
您可以通過使用System.Linq中的 、 和SelectMany()的.Select()組合來實作您想要做的事情。.Where().Contains()
稍微簡化,通過使用ints 作為組值而不是char,這是一個可能的實作:
public class GroupedOwnerAndPetCategory
{
public string Owner { get; set; }
public string PetCategory { get; set; }
public int Group { get; set; }
}
var grouped = petCategoriesOwners
.SelectMany((ownerPetMix, index) => petCategoryOwner
.Where(ownerPetPair =>
ownerPetMix.Owners.Contains(ownerPetPair.Owner) &&
ownerPetMix.PetCategories.Contains(ownerPetPair.PetCategory))
.Select(ownerPetPair => new GroupedOwnerAndPetCategory
{
Owner = ownerPetPair.Owner,
PetCategory = ownerPetPair.PetCategory,
Group = index
}))
.ToList();
使用您的示例輸入,grouped包含以下條目:
Higa Terry 0
Higa Charlotte 0
Oliver Terry 0
Oliver Charlotte 0
Oliver Chausie 1
Price Chausie 1
Liam Terry 2
Liam Chartreux 2
示例小提琴在這里。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/497415.html
下一篇:處理字典值以防它為空
