[英]C# Remove duplicated objects from list and increase first
我有一個對象列表 => class Example { int quantity; string name; string comment; }
class Example { int quantity; string name; string comment; }
我想刪除所有重復class Example { int quantity; string name; string comment; }
並通過具有相同name
和comment
的重復項的數量來增加quantity
。
例子:
[
{quantity: 1, name: "Hello", comment: "Hello there"},
{quantity: 2, name: "Bye", comment: "Good bye"},
{quantity: 1, name: "Hi", comment: "Hi there"},
{quantity: 1, name: "Hello", comment: "Hello there"},
{quantity: 1, name: "Bye", comment: "Good bye"},
]
結果應該是:
[
{quantity: 2, name: "Hello", comment: "Hello there"},
{quantity: 3, name: "Bye", comment: "Good bye"},
{quantity: 1, name: "Hi", comment: "Hi there"}
]
我想刪除所有重復項
您尚未定義兩個示例對象何時“重復”。 我猜,你的意思是說,如果兩個 Examples 對象的屬性Name
和Comment
具有相同的值,那么它們就是重復的。
通常,您可以使用Enumerable.GroupBy的重載之一來查找重復項。 使用帶有參數resultSelector
的重載來准確定義您想要的結果。
IEnumerable<Example> examples = ...
var result = examples.GroupBy(
// key: Name-Comment
example => new
{
Name = example.Name,
Comment = example.Comment,
}
// parameter resultSelector: for every Name/Comment combination and all
// Examples with this Name/Comment combination make one new example:
(nameCommentCombination, examplesWithThisNameCommentCombination) => new Example
{
Name = nameCommentCombination.Name,
Comment = nameCommentCombination.Comment,
// Quantity is the sum of all Quantities of all Examples with this
// Name/Comment combination
Quantity = examplesWithThisNameCommentCombination
.Select(example => example.Quantity)
.Sum(),
});
這僅在您想要精確的字符串相等時才有效。 “你好”和“你好”是否相等? 那么“Déjà vu”和“Deja vu”呢? 您想要名稱和評論不區分大小寫嗎? 那么變音字符呢?
如果您想要的不僅僅是簡單的字符串相等,請考慮創建一個 ExampleComparer class。
class ExampleComparer : EqualityComparer<Example>
{
... // TODO: implement
}
用法是:
IEnumerable<Example> examples = ...
IEqualityComparer<Example> comparer = ...
var result = examples.GroupBy(example => example, // key
// resultSelector:
(key, examplesWithThisKey) => new Example
{
Name = key.Name,
Comment = key.Comment,
Quantity = examplesWithThiskey.Sum(example => example.Quantity),
},
comparer);
class ExampleComparer : EqualityComparer<Example>
{
public static IEqualityComparer<Example> ByNameComment {get;} = new ExampleComparer;
private static IEqualityComparer<string> NameComparer => StringComparer.CurrentCultureIgnoreCase;
private static IEqualityComparer<string> CommentComparer => StringComparer.CurrentCultureIgnoreCase;
我選擇了兩個單獨的字符串比較器,所以如果稍后您決定不同的比較,例如名稱必須完全匹配,那么您只需在此處更改它。
public override bool Equals (Example x, Example y)
{
// almost every Equals method starts with the following three lines
if (x == null) return y == null; // true if both null
if (y == null) return false; // false, because x not null
if (Object.ReferenceEquals(x, y)) return true; // same object
// return true if both examples are considered equal:
return NameComparer.Equals(x.Name, y.Name)
&& CommentComparer.Equals(x.Comment, y.Comment);
}
public override int GetHashCode(Example x)
{
if (x == null) return 5447125; // just a number
return NameComparer.GetHashCode(x.Name)
^ CommentComparer.GetHashCode(x.Comment);
}
注意:如果名稱或評論是 null 或為空,這也將起作用!
我使用了operator ^ (XOR)
,因為如果只有兩個字段需要考慮,這會給出一個相當好的 hash 。 如果您認為絕大多數示例具有唯一名稱,請考慮僅檢查屬性名稱:
return NameComparer.GetHashCode(x.Name);
因為方法Equals
使用 NameComparer 和 CommentComparer 來檢查相等性,所以請確保使用相同的比較器來計算 HashCode。
這是一個簡單的解決方案,它可以在 List tata 中為您提供答案,但如果您願意,您可以執行.ToArray()。
public class Example
{
public int quantity;
public string name;
public string comment;
}
Example[] toto = new Example[]
{
new Example
{
quantity = 1,
name = "Hello",
comment = "Hello there"
},
new Example
{
quantity = 2,
name = "Bye",
comment = "Good bye"
},
new Example
{
quantity = 1,
name = "Hi",
comment = "Hi there"
},
new Example
{
quantity = 1,
name = "Hello",
comment = "Hello there"
},
new Example
{
quantity = 1,
name = "Bye",
comment = "Good bye"
}
};
List<Example> tata = new List<Example>();
foreach (Example exa in toto)
{
bool found = false;
foreach (Example exb in tata)
{
if (exb.name == exa.name && exb.comment == exa.comment)
{
exb.quantity += exa.quantity;
found = true;
break;
}
}
if (!found)
{
tata.Add(exa);
}
}
LINQ 是一個很好的練習!
這是我要做的:
Example[] before = new Example[]
{
new Example { Quantity = 1, Name = "Hello", Comment = "Hello there" },
new Example { Quantity = 2, Name = "Bye", Comment = "Good bye" },
new Example { Quantity = 1, Name = "Hi", Comment = "Hi there" },
new Example { Quantity = 1, Name = "Hello", Comment = "Hello there" },
new Example { Quantity = 1, Name = "Bye", Comment = "Good bye" },
};
Example[] after =
before
.GroupBy(x => new { x.Name, x.Comment }, x => x.Quantity)
.Select(x => new Example { Quantity = x.Sum(), Name = x.Key.Name, Comment = x.Key.Comment })
.ToArray();
這給出了:
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.