我有一个大的列表<>名称/值对,并且需要能够查找此列表中是否存在特定名称...如果是,则更新该值,如果不是,则创建新的名称/值对并将其附加到我的列表。
执行此操作的Lambda语法是什么?
我尝试使用.Where .DefaultIfEmpty,但它只返回一个空对象,但不会将其附加到我原来的'myList'
myList.Where(x => x.Name == 'some name').DefaultIfEmpty(new myobj(){ Name = 'some name').First().Value = 'some value';
我必须这四个多个名字,所以如果我有一个简单的语法,这将使它很棒=)
答案 0 :(得分:5)
您可以使用此扩展方法:
public static void UpdateOrAdd(this List<myobj> source,
string name, object value)
{
var obj = source.FirstOrDefault(x => x.Name == name);
if (obj == null)
{
obj = new myobj { Name = name };
source.Add(obj);
}
obj.Value = value;
}
用法:
myList.UpdateOrAdd("some name", "some value");
但考虑使用字典,正如@Sam建议的那样。
答案 1 :(得分:3)
您的实际查询只是获取满足条件的第一个项目。 LINQ用于查询而不是用于修改集合,因此您不应将该项作为查询的一部分添加到集合中;这是处理查询的一部分。
var match = list.FirstOrDefault(x => x.Name == "some name");
if(match != null)
match.Value = "something else";
else
list.Add(new MyObject(){...});
如果你想要一个更通用的GetOrAdd
方法,你也可以制作一个:
public static T GetOrAdd<T>(this IList<T> list, Func<T, bool> predicate,
Func<T> constructor)
{
var match = list.FirstOrDefault(predicate);
if(match == null)
{
match = constructor();
list.Add(match);
}
return match;
}
使用它你可以编写如下内容:
var item = list.GetOrAdd(obj => obj.Name == "Some Name", () => new MyObj(){...});
item.Value = "Some Value";
完成此操作后,请强烈考虑为此集合使用Dictionary
而不是List
对,因为可以根据密钥更有效地搜索它。
如果您确实有Dictionary
,那么执行此操作的代码将非常简单:
dictionary["some name"] = "some value";
除了缩短代码外,它还能更快地执行 。
答案 2 :(得分:1)
恰好我只是使用Dictionary
为我自己的项目写了这个类:
public class CachedLoader<K, T> : Dictionary<K, T>
{
private Func<K,T> GetItem = null;
public CachedLoader(Func<K,T> getItem)
{
this.GetItem = getItem;
}
public new T this[K key]
{
get
{
if (!base.ContainsKey(key)) base[key] = GetItem(key);
return base[key];
}
}
}
构造函数使用lambda表达式来加载数据。您可以这样使用它:
CachedLoader<Guid, Employee> MOEmployees
= new CachedLoader<Guid, Employee>(id => EmployeeManager.List(id));
你会像这样消耗它:
Guid employeeId = ...;
MOEmployees[employeeId]
没有必要从消耗数据的代码中显式创建/加载项目,因为类会为您处理它 - 您只需在构造函数中指定如何执行它。您可以根据需要调整构造函数以创建值。
如果您遇到List
,那么您也可以轻松地将其调整为该结构。
答案 3 :(得分:0)
DefaultIfEmpty不会附加到列表。如果传递给它的集合为空,则返回指定的值。所以在你的情况下,什么都不会发生,因为你没有把结果分配给任何东西;只是让它被丢弃。
没有一个简单的lambda链可以做你想要的。你必须做两个步骤。首先,您可以查看是否有任何结果与您要查找的内容相匹配,如果没有则附加。
var defaultObj = new myobj() { Name = "default name", Value = "default value"};
if(!list.Any(x => x.Name == "some name")){
list.Add(defaultObj);
}
编辑:在回复评论时,我确实错过了更新原文。你可以这样做:
var obj = list.FirstOrDefault(x => x.Name == "some name");
if(obj == null){
obj = new myobj() { Name = "default name" };
list.Add(obj);
}
obj.Value = "some value";
答案 4 :(得分:0)
使用Any()
if(list.Any(x => x.Name == "some name"))
{
// Replace
}
else
{
// Add
}