![](/img/trans.png)
[英]How can I order in Linq Select Distinct if ordered by an Included entity?
[英]How can I select distinct and ordered data into a generic list from multiple lists?
我有幾個通用列表,其中包含一些共享的數據和一些唯一的數據。 它們包含相同類的數據,但使用不同的參數(單元)填充。 因此,所有通用列表都屬於這種類型: List<PriceVarianceData>
我要對這些通用列表進行的操作是從它們中提取它們包含的獨特數據的子集,然后對合並后的列表進行排序。
更具體地說,要查詢的列表具有以下結構:
public class PriceVarianceData
{
public String Unit { get; set; }
public String ShortName { get; set; }
public String ItemCode { get; set; }
public String Description { get; set; }
public String PriceWeek { get; set; }
public String Week { get; set; }
public String Price { get; set; }
public String Variance { get; set; }
public String VarianceAverage { get; set; }
public int RegionOrder { get; set; }
public int ContractPrice { get; set; }
}
...並且我要將數據提取到的通用列表具有以下結構:
public class PriceVarianceSupersetDisplayData
{
public String ShortName { get; set; }
public String ItemCode { get; set; }
public String Description { get; set; }
}
單位將具有一些相同的ShortName + ItemCode + Description值,我只希望這些值的唯一組合-不應重復ShortName + ItemCode + Description,但是,如果它們的值不同,則應將它們考慮在內獨特/不同。 因此,提取的數據應在訂購后如下所示:
SHORTNAME ITEMCODE DESCRIPTION
--------- -------- -----------
Fakeroo 001 Stratoblaster
Fender 001 Stratocaster
Gibson 001 335
Gibson 001 SG
Fender 002 Telecaster
Gibson 002 Les Paul
Carvin 003 Knife
Carvin 003 L6S
我(認為我)知道這里需要的是LINQ查詢; 用偽代碼,類似於:
List<PriceVarianceSupersetDisplayData> displayDataAmalgamated = select distinct ShortName, ItemCode, Description from craftworksPVDList, chophousePVDList, gordonbierschPVDList, oldchicagoPVDList, oldchifranchisePVDList, rockbottomPVDList order by ItemCode then by ShortName, then by Description
...但是不知道如何將其從偽代碼轉換為真正的LINQ。
user3185569的答案和Zoran Horvat的答案結合使用似乎很奏效,只是我顯然沒有得到不同的價值。 我的第一個線索是,最終通用列表中的條目數量似乎太高了。
然后,我查看了列表中的前兩個條目,它們是(或至少看起來是相同的):
這是我正在使用的代碼; 如前所述,它是前兩個答案的組合:
private List<PriceVarianceSupersetDisplayData> GetSharedDisplayDataForAll()
{
Func<PriceVarianceData, PriceVarianceSupersetDisplayData> selector =
(p => new PriceVarianceSupersetDisplayData()
{
ShortName = p.ShortName,
ItemCode = p.ItemCode,
Description = p.Description
});
List<PriceVarianceSupersetDisplayData> displayDataAmalgamated =
craftworksPVDList.Concat(chophousePVDList)
.Concat(chophousePVDList)
.Concat(gordonbierschPVDList)
.Concat(oldchicagoPVDList)
.Concat(oldchifranchisePVDList)
.Concat(rockbottomPVDList).Select(selector)
.Distinct()
.OrderBy(x => x.ItemCode)
.ThenBy(x => x.ShortName)
.ThenBy(x => x.Description).ToList();
return displayDataAmalgamated;
}
為什么Distinct()返回重復的值?
首先實現Equals
和GetHashCode
。 然后,您可以add
所有列表add
到一個列表中, select
三個鍵,然后使用Distinct
刪除重復項並使用OrderBy
- ThenBy
進行排序:
public class PriceVarianceSupersetDisplayData
{
public String ShortName { get; set; }
public String ItemCode { get; set; }
public String Description { get; set; }
public override bool Equals(object obj)
{
var pv = obj as PriceVarianceSupersetDisplayData;
if (pv == null)
return false;
return this.ShortName == pv.ShortName
&& this.ItemCode == pv.ItemCode
&& this.Description == pv.Description;
}
public override int GetHashCode()
{
return 0;
}
}
Func<PriceVarianceData, PriceVarianceSupersetDisplayData> selector =
(p => new PriceVarianceSupersetDisplayData()
{
ShortName = p.ShortName,
ItemCode = p.ItemCode,
Description = p.Description
});
List<PriceVarianceSupersetDisplayData> results =
craftworksPVDList.Concat(chophousePVDList)
.Concat(gordonbierschPVDList)
.Concat(oldchicagoPVDList)
.Concat(oldchifranchisePVDList)
.Concat(rockbottomPVDList).Select(selector).Distinct()
.OrderBy(x=> x.ItemCode).ThenBy(x=> x.ShortName)
.ThenBy(x=> x.Description).ToList();
(無需通過使用Tuple
的Equals
實現Equals
或GetHashCode
)
List<PriceVarianceSupersetDisplayData> results =
craftworksPVDList.Concat(chophousePVDList)
.Concat(gordonbierschPVDList)
.Concat(oldchicagoPVDList)
.Concat(oldchifranchisePVDList)
.Concat(rockbottomPVDList).Select(x=> Tuple.Create(x.ShortName, x.ItemCode, x.Description))
.Distinct().OrderBy(x=> x.Item2).ThenBy(x=> x.Item1).ThenBy(x=> x.Item3)
.Select(t=> new PriceVarianceSupersetDisplayData()
{
ShortName = t.Item1,
ItemCode = t.Item2,
Description = t.Item3
}).ToList();
如果您希望僅使用所有部分列表中的不同數據來構造另一個列表,則可以通過使用Concat LINQ方法將它們結合在一起,然后最后使用Distinct LINQ方法來輕松地做到這一點:
list1.Concat(list2).Concat(list3)...Concat(listN).Distinct();
假設類是值類型。 由於您使用的是非常簡單的類,因此建議您在它們中實現值類型語義,然后這種列表操作將變得很簡單。
添加值類型語義意味着重寫GetHashCode,Equals,添加運算符==和運算符!=,並最好使用其自己的Equals(T)實現IEnumerable。 正如我所說,完成所有這些操作后,列表操作將變得微不足道。
排序數據可以在最后添加,例如:
list1
.Concat(list2)
.Concat(list3)
...
.Concat(listN)
.Distinct()
.OrderBy(x => x.ItemCode)
.ThenBy(x => x.ShortName)
.ThenBy(x => x.Description);
如果您不想打擾Equals
/ GetHashCode
覆蓋或實現IEqualityComparer<PriceVarianceSupersetDisplayData
,這是使Distinct
在其他答案中正常工作所必需的,則最簡單的方法是使用中間匿名類型投影(因為編譯器會自動實現正確的比較)匿名類型的值語義),如下所示:
var displayDataAmalgamated =
new[] { craftworksPVDList, chophousePVDList, gordonbierschPVDList, oldchicagoPVDList, oldchifranchisePVDList, rockbottomPVDList }
.SelectMany(list => list.Select(item => new { item.ShortName, item.ItemCode, item.Description }))
.Distinct()
.Select(item => new PriceVarianceSupersetDisplayData { ShortName = item.ShortName, ItemCode = item.ItemCode, Description = item.Description })
.OrderBy(item => item.ShortName).ThenBy(item => item.ItemCode)
.ToList();
或對group by
使用查詢語法:
var displayDataAmalgamated = (
from list in new[] { craftworksPVDList, chophousePVDList, gordonbierschPVDList, oldchicagoPVDList, oldchifranchisePVDList, rockbottomPVDList }
from item in list
group item by new { item.ShortName, item.ItemCode, item.Description } into g
orderby g.Key.ShortName, g.Key.Description
select new PriceVarianceSupersetDisplayData { ShortName = g.Key.ShortName, ItemCode = g.Key.ItemCode, Description = g.Key.Description }
).ToList();
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.