of Name / Value" and you need to find out if a ...">

Update a property or create a new item if it does not exist. Lambda C #

I have large pairs "List <> of Name / Value" and you need to find out if a specific name exists in this list ... if this is an update of this value, if NOT then create a new Name / Value pair and add it to your list .

What is the Lambda syntax for this?

I tried using .Where.DefaultIfEmpty, but it just returns an empty object, but does not add it to my original 'myList'

myList.Where(x => x.Name == 'some name').DefaultIfEmpty(new myobj(){ Name = 'some name').First().Value = 'some value'; 

I have to do this four plural Names, so if I had a simple syntax that would make it big =)

+4
source share
5 answers

Your actual request is simply getting the first item that matches the condition. LINQ is not intended to be a query to modify the collection, so you should not add an item to the collection as part of the query; do this as part of request processing.

 var match = list.FirstOrDefault(x => x.Name == "some name"); if(match != null) match.Value = "something else"; else list.Add(new MyObject(){...}); 

If you want to use the more general GetOrAdd method, you can do it as well:

 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; } 

Using this, you can write something like:

 var item = list.GetOrAdd(obj => obj.Name == "Some Name", () => new MyObj(){...}); item.Value = "Some Value"; 

Having done this, please, it is strongly recommended to use the Dictionary for this collection, and not for the List pair, since it can be more efficiently searched based on the key.

If you have a Dictionary , then the code for this will be as simple as:

 dictionary["some name"] = "some value"; 

And in addition to shortening the code, it will work much faster.

+3
source

You can use this extension method:

 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; } 

Using:

 myList.UpdateOrAdd("some name", "some value"); 

But consider using a dictionary , as @Sam suggested.

+5
source

It just so happened that I just wrote this class for my own project using 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]; } } } 

The constructor accepts a lambda expression for loading data. You can use it as follows:

 CachedLoader<Guid, Employee> MOEmployees = new CachedLoader<Guid, Employee>(id => EmployeeManager.List(id)); 

And you would consume it like this:

 Guid employeeId = ...; MOEmployees[employeeId] 

There is no need to explicitly create / load an element from the code from which you consume data, because the class processes it for you - you just need to specify how to do this in the constructor. You would adapt the constructor to create the value, but you need it.

If you are stuck on a List , you can easily adapt it to this structure too.

+1
source

DefaultIfEmpty does not add to lists. It returns the specified value if the collection passed to it is empty. So in your case nothing will happen because you are not assigning the result to anything; just letting it drop.

There is no simple lambda chain to do what you want. You need to take two steps. Firstly, you can see if there are any results that match what you are looking for, and then add if not.

 var defaultObj = new myobj() { Name = "default name", Value = "default value"}; if(!list.Any(x => x.Name == "some name")){ list.Add(defaultObj); } 

Edit: In response to a comment, I skipped updating the original. You can do something like this:

 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"; 
0
source

Use Any()

 if(list.Any(x => x.Name == "some name")) { // Replace } else { // Add } 
0
source

Source: https://habr.com/ru/post/1490515/


All Articles