dMilan
dMilan

Reputation: 257

How to compare two lists and change one property

I have a class:

public class Doc
{
   public int Id {get; set;}
   public string Name {get; set;}
   public bool IsActive {get; set;}
}

And two lists of Doc type.

How to write LINQ to compare these list and change IsActive property of first list if contains id from second list.

Upvotes: 1

Views: 5156

Answers (5)

Fabjan
Fabjan

Reputation: 13676

It's better to use the HashSet<T> collection for such operations, it has fast O(1) lookups and there is no real reason to use LINQ for changing property values here. True, we have to create another collection here and it takes time to allocate resources initialize it etc. but if there is one million records it will give huge performance boost.

Provided that docs1 is collection where you would like to change IsActive to true if docs2 collection has Id, you can use :

var ids = new HashSet<int>(docs2.Select(d => d.Id));
foreach(var doc in docs1) 
{
                  // .Contains implementation in HashSet has fast O(1) lookups
   doc.IsActive = ids.Contains(doc.Id); 
}

Upvotes: 1

Harald Coppoolse
Harald Coppoolse

Reputation: 30464

You wrote:

How to write linq to compare these list and change "IsActive" propety of first list if contains id from second list.

Your first list does not have an IsActive property, however the elements of your list have one. Therefore I assume you want the following:

How do I get a sequence of all elements in the first list that have an Id of any of the elements in the second list, so I can change the IsActive properties of those elements.

LINQ is used to enumerate over objects. You can't change the object in the linq statement

If you want to change the objects, you'll have to enumerate over them, for instance with ForEach.

IEnumerable<int> activeIds = secondList.Select(item => item.Id);
IEnumerable<Doc> activeDocs = firstList.Where(item => activedIds.Contains(item.Id));

foreach (Doc activeDoc in activeDocs)
{
    activeDoc.IsActive = true;
}

Beware: I did not change ISActive for all inActive docs. If you want that you'll have to foreach all elements from your firstList:

IEnumerable<int> activeIds = secondList.Select(item => item.Id);
foreach (Doc doc in firstList)
{
    doc.IsActive = activeIds.Contains(doc.Id);
}

Upvotes: 0

rickythefox
rickythefox

Reputation: 6851

Given that your target list is named targetDocs and the list you want to check for document existance is srcDocs try something like (don't have access to a compiler here so can't test):

targetDocs.ForEach(d => d.IsActive = srcDocs.Any(sd => sd.id == d.Id))

I'm assuming that we are talking about Lists and not other collection types as the ForEach extension method is defined for Lists.

Upvotes: 6

Aliaksei Futryn
Aliaksei Futryn

Reputation: 461

You can create your own static method which is responsible for checking active property. I've used enumerators here, it works fast and easy to understand.

static class Program
{

    static void Main(string[] args)
    {
        List<Data> firstInstance = new List<Data>
        {
            new Data { Id = 1, IsActive = false },
            new Data { Id = 2, IsActive = false }
        };

        List<Data> secondInstance = new List<Data>
        {
            new Data { Id = 1, IsActive = false },
            new Data { Id = 3, IsActive = false }
        };

        firstInstance.CheckActive(secondInstance);
    }

    static void CheckActive(this List<Data> firstInstance, List<Data> secondInstance)
    {
        using (IEnumerator<Data> firstEnumerator = firstInstance.GetEnumerator(), secondEnumerator = secondInstance.GetEnumerator())
        {
            while (true)
            {
                if (!firstEnumerator.MoveNext() || !secondEnumerator.MoveNext()) break;
                if (firstEnumerator.Current.Id == secondEnumerator.Current.Id) firstEnumerator.Current.IsActive = true;
            }
        }
    }
}

class Data
{
    public int Id { get; set; }
    public bool IsActive { get; set; }
}

Upvotes: 0

marsahllDTitch
marsahllDTitch

Reputation: 309

You can use this solution without using linq

foreach(Doc x in list1){ 
  foreach(Doc y in list2){
    if(x.id == y.id){
       y.IsActive = true;
                    }
                        }
                      }

Upvotes: -1

Related Questions