我在这里看到了一个类似的问题,并提供了很好的解决方案: Simplest way to form a union of two lists
但问题是,当每个列表中只有一个参数(int值)时,它可以工作。我有这个要求,将包含同一类对象的5个不同列表组合在一起,没有数据冗余,最终列表应按int值的升序排序。
示例:
Class Company //data Class
{
int companyNo;
string Name;
}
Class CompanyList : List<Company>
{
.................
public CompanyList GetList(int userID)
{
.....
}
}
类公司有一个pulic方法返回对应于搜索条件的公司列表,让我们用户ID。
CompanyList list1 = CompanyList .GetList(userID1);
CompanyList list2 = CompanyList .GetList(userID2);
CompanyList list3 = CompanyList .GetList(userID3);
CompanyList list4 = CompanyList .GetList(userID4);
CompanyList list5 = CompanyList .GetList(userID5);
The solution I implemented is (worked well):
CompanyList _finalList = list1;
*foreach (CompanyList _list in {_list2 ,_list3 ,_list4 ,_list5}) //loop thorugh all other list
{
foreach (Company item in _list)
{
for (int i = 0; i <= _finalList.Count - 1; i++)
{
if (_finalList.Item(i).CompanyNo== item.CompanyNo)
//***EXIT TAKE NEXT LIST - GO TO *
}
if (i == _finalList.Count - 1) //else check end of first list
{
//company no. not yet encountered(new)
int pos = 0;
foreach (Company companyInfo in _finalList) //search for position for new company no.
{
if (companyInfo.CompanyNo> item.CompanyNo)
{
break;
}
else
{
pos = pos + 1; //increment position
}
}
_finalList.Insert(pos, item); 'Add new item
}
}
}
**代码从VB.Net转换为C#。在这里,我找不到该行的等价代码片段,因此将其替换为概念。
我不是专家C#程序员,只是想知道是否有更好或更简单的方法来做到这一点?
数据示例:
Input:
list1[0] = {0,"TCS"};
list1[1] = {1,"Infosys"};
list2[0] = {8,"IBM"};
list3[1] = {1,"Infosys"};
list4[0] = {0,"TCS"};
list5[0] = {9,"Accenture"};
list5[1] = {6,"HCL"};
Output:
finalList[0] = {0,"TCS"};
finalList[1] = {1,"Infosys"};
finalList[2] = {6,"HCL"};
finalList[3] = {8,"IBM"};
finalList[4] = {9,"Accenture"};
此致 SJ
答案 0 :(得分:2)
您可以使用GroupBy或Union来删除重复... Union使得一个更清洁的linq(我认为),但要么可以工作......缺点是在这种情况下你还需要一个自定义IEqualityComparer,因为等于您的公司对象将返回false(因为它们是不同的实例)...另一种方法是让您的Company
类实现IEqualityComparer,并将我实现该接口的代码复制到您的Company
类中。 / p>
// Union gives you a unique list if it knows how to compare the objects properly
var companyEqualityComparer = new CompanyEqualityComparer();
foreach (var companyList in new List<List<Company>>(){list2, list3, list4, list5})
{
combinedList = combinedList.Union(companyList, companyEqualityComparer);
}
// Order your output list
var finalList = combinedList.OrderBy(c => c.companyNo).ToList();
定义您的CompanyEqualityComparer ...
// CompanyEqualityComparer which is needed since your companies are different instances
public class CompanyEqualityComparer : IEqualityComparer<Company>
{
public bool Equals(Company x, Company y)
{
return x.companyNo.Equals(y.companyNo);
}
public int GetHashCode(Company obj)
{
return obj.companyNo.GetHashCode();
}
}
答案 1 :(得分:2)
与Habib的解决方案类似,但更简洁,更完整。
int[] userIDs = new[] { userID1, userID2, userID3, userID4, userID5 };
IEnumerable<Company> distinctCompanies =
from companyList in userIDs.Select(CompanyList.GetList)
from company in companyList
group company by company.companyNo into companiesWithSameNo
select companiesWithSameNo.First();
CompanyList finalList = new CompanyList();
finalList.AddRange(distinctCompanies);
您可能在CompanyList中有一个直接接受IEnumerable<Company>
的构造函数,因此您可以直接在其中传递distinctCompanies
。
答案 2 :(得分:2)
好的,所以你有很多东西的序列,在你的情况下,“某些东西”是Company
,它不会覆盖object.Equals
或object.HashCode
。
所以,像这样的新扩展可能会很有用
public static IEnumerable<T> Union(
this IEnumerable<T> source,
IEqualityComparer<T> comparer,
params IEnumerable<T>[] others)
{
if (comparer == null)
{
comparer = EqualityComparer<T>.Default;
}
var result = source.Distinct(comparer);
foreach(var o in source)
{
if (o == null)
{
continue;
}
result = result.Union(o, comparer);
}
return result;
}
要实现此功能以及使IEqualityComparer
简单易用的其他功能,您可以将此类添加到代码中,
public class EqualityComparerImproved<T> : EqaulityComparer<T>
{
private readonly Func<T, T> equalityComparison;
private readonly Func<T, int> hashGenerator;
private EqualityComparerImproved(
Func<T, T> equalityComparison,
Func<T, int> hashGenerator)
{
this.equalityComparison = equalityComparison;
this.hashGenerator = hashGenerator;
}
public static EqualityComparerImproved<T> Create
Func<T, T> equalityComparison,
Func<T, int> hashGenerator)
{
if (equalityComparison == null)
{
throw new ArgumentNullException("equalityComparison");
}
if (hashGenerator == null)
{
throw new ArgumentNullException("hashGenerator");
}
return new EqualityComparerImproved<T>(
equalityComparison,
hashGenerator);
}
public override bool Equals(T x, T y)
{
return this.equalityComparison(x, y);
}
public override int GetHashCode(T obj)
{
return this.hashGenerator(obj);
}
}
一旦这两个代码完全存在,你可以做到
var output = list1.Union(
EqualityComparerImproved<Company>.Create(
(x, y) => x.companyNo == y.companyNo && x.Name == y.Name,
(obj) =>
{
unchecked // Overflow is fine, just wrap
{
int hash = 17;
hash = hash * 23 + obj.companyNo;
hash = hash * 23 + obj.Name.GetHashCode();
return hash;
}
},
list2,
list3,
list4,
list5);
或如果companyNo
是唯一键,
var output = list1.Union(
EqualityComparerImproved<Company>.Create(
(x, y) => x.companyNo == y.companyNo,
(obj) => obj.companyNo),
list2,
list3,
list4,
list5);
就足够了。
答案 3 :(得分:1)
我认为你需要这样的东西:
List<Company> inputList = //Get your input List
List<Company> outputList = inputList.GroupBy(r => r.companyNo)
.Select(grp => new Company
{
companyNo = grp.Key,
Name = grp.First().Name,
})
.OrderBy(r=> r.companyNo)
.ToList();