我有一个具有以下属性的类
id
(类型:唯一long
),name
(类型:string
),版本主要(VM
)(类型:{{1} }),版本次要(long
)(类型:Vm
)
我创建了这个类的列表,列表如下所示
long
我想根据Version Major和版本minor删除列表中的重复项。最终列表应如下所示
ID Name VM Vm
1 ssim 2 1
2 SSim 3 1
3 Counter 5 1
4 Counter 6 2
5 Counter 6 5
答案 0 :(得分:2)
这样的事情,我想:
public class Product
{
public Product(long id, string name, int major, int minor)
{
this.Id = id;
this.Name = name;
this.Major = major;
this.Minor = minor;
}
public long Id { get; set; }
public int Major { get; set; }
public int Minor { get; set; }
public string Name { get; set; }
}
private static void Main()
{
IEnumerable<Product> products = new List<Product>
{
new Product(1, "ssim", 2, 1),
new Product(2, "SSim", 3, 1),
new Product(3, "Counter", 5, 1),
new Product(4, "Counter", 6, 2),
new Product(5, "Counter", 6, 5)
};
IEnumerable<Product> distinctProducts =
(from x in products group x by x.Name.ToLower() into g select g.OrderByDescending(y => y.Major).ThenByDescending(y => y.Minor).First()).OrderBy(x => x.Name).ToList();
}
答案 1 :(得分:2)
所以你想要每个名字的最大版本。
你可以像这样使用linq:
void Main()
{
var versions = new List<Version>
{
new Version(1,2, "a"),
new Version(1,3, "a"),
new Version(1,3, "b"),
new Version(1,4, "b"),
new Version(1,1, "b"),
new Version(2,3, "c")
};
var distinctVersions = versions
.GroupBy(g => g.name.ToLowerInvariant())
.Select(g => g.ToList().OrderBy(x => x.major).ThenBy(x => x.minor).Last())
.ToList();
}
答案 2 :(得分:1)
说你的班级是ProgramEntry
:
public class ProgramEntry {
public long Id;
public string Name;
public long VM;
public long Vm;
public ProgramEntry (long id, string name, long vM, long vm) {
Id = id;
Name = name;
VM = vM;
Vm = vm;
}
public override string ToString () {
return this.Id+":"+this.Name+"("+this.VM+"."+this.Vm+")";
}
}
(是的,使用公共字段不是一个好习惯,但只是一个快速而肮脏的解决方案)
现在您可以按版本(第一个主要版本,然后是次要版本)订购它们:
List<ProgramEntry> programs = new List<ProgramEntry>();
//fill list with programs
var order = programs.OrderBy(x => -x.VM).ThenBy(x => -x.Vm);
这会导致IEnumerable<ProgramEntry>
排序最大的主要优先,如果是等同的主要,最大的次要优先。
接下来,您可以使用this duplicate filter过滤掉具有相同Name
的元素:
List<ProgramEntry> result = order.DistinctBy(x => x.Name).ToList();
DistinctBy
是MoreLINQ库的一部分。或者您可以使用扩展类
public static class Foo {
public static IEnumerable<TSource> DistinctBy<TSource, TKey>
(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector) {
HashSet<TKey> seenKeys = new HashSet<TKey>();
foreach (TSource element in source) {
if (seenKeys.Add(keySelector(element))) {
yield return element;
}
}
}
}
演示(使用csharp
交互式shell):
$ csharp
Mono C# Shell, type "help;" for help
Enter statements below.
csharp> public class ProgramEntry {
>
> public long Id;
> public string Name;
> public long VM;
> public long Vm;
>
> public ProgramEntry (long id, string name, long vM, long vm) {
> Id = id;
> Name = name;
> VM = vM;
> Vm = vm;
> }
>
> public override string ToString () {
> return this.Id+":"+this.Name+"("+this.VM+"."+this.Vm+")";
> }
>
> }
csharp> List<ProgramEntry> programs = new List<ProgramEntry>();
csharp> programs.Add(new ProgramEntry(1,"ssim",2,1));
csharp> programs.Add(new ProgramEntry(2,"ssim",3,1));
csharp> programs.Add(new ProgramEntry(3,"Counter",5,1));
csharp> programs.Add(new ProgramEntry(4,"Counter",6,2));
csharp> programs.Add(new ProgramEntry(5,"Counter",6,5));
csharp> programs
{ 1:ssim(2.1), 2:ssim(3.1), 3:Counter(5.1), 4:Counter(6.2), 5:Counter(6.5) }
csharp> var order = programs.OrderBy(x => -x.VM).ThenBy(x => -x.Vm);
csharp> order
{ 5:Counter(6.5), 4:Counter(6.2), 3:Counter(5.1), 2:ssim(3.1), 1:ssim(2.1) }
csharp> List<ProgramEntry> result = order.DistinctBy(x => x.Name).ToList();
csharp> result
{ 5:Counter(6.5), 2:ssim(3.1) }
这是预期的行为吗?
答案 3 :(得分:0)
我们假设这个类类似于你的数据:
public class VerX
{
public int ID { get; set; }
public string Name { get; set; }
public int VerMajor { get; set; }
public int VerMinor { get; set; }
}
对于您的样本,这是填充此数据的方式:
var list = new List<VerX>
{
new VerX { ID = 1, Name = "ssim", VerMajor = 2, VerMinor = 1 },
new VerX { ID = 2, Name = "SSim", VerMajor = 3, VerMinor = 1 },
new VerX { ID = 3, Name = "Counter", VerMajor = 5, VerMinor = 1 },
new VerX { ID = 4, Name = "Counter", VerMajor = 6, VerMinor = 2 },
new VerX { ID = 5, Name = "Counter", VerMajor = 6, VerMinor = 5 },
};
现在,让我们创建一个循环,为您提供所需的结果:
// First create new list that would hold the results
var listNew = new List<VerX>();
// Select distinct names from data (using ToLower, so casing does not matter)
var names = list.Select(t => t.Name.ToLower()).Distinct().ToList();
// Loop through each of distinct name
foreach (var name in names)
{
// With LINQ, select item whose name matches and sort list by VerMajor
// descending and VerMinor descending and take first item.
var item = list.Where(t => t.Name.Equals(name, StringComparison.InvariantCultureIgnoreCase))
.OrderByDescending(t => t.VerMajor)
.ThenByDescending(t => t.VerMinor)
.FirstOrDefault();
// If item not found (although it should be found!), continue the loop
if (item == null)
continue;
// Add item to new list
listNew.Add(item);
}
// At the end of the loop, the listNew contains items as in your proposed result.
可以通过更复杂的LINQ查询获得相同的foreach循环:
// Select distinct names as in first case
var names = list.Select(t => t.Name.ToLower()).Distinct().ToList();
// Construct listNew from names based on same algorithm as before, but using LINQ this time.
var listNew = names
.Select(name => list.Where(t => t.Name.Equals(name, StringComparison.InvariantCultureIgnoreCase))
.OrderByDescending(t => t.VerMajor)
.ThenByDescending(t => t.VerMinor)
.FirstOrDefault())
.Where(item => item != null)
.ToList();
// Here, listNew contains your desired result.
根据您想要的结果,这会根据最大VerMajor和最大VerMinor为您提供按名称分组的结果。
答案 4 :(得分:0)
我认为您可以使用此代码轻松完成您的要求:
var groupsByName = myItems.GroupBy(x => x.Name.ToLower());
var distinctItems = groupsByName.Select(x => x.ToList()
.OrderByDescending(y => y.VM)
.ThenByDescending(z => z.Vm).First())
.OrderBy(k => k.Name).ToList();