Reputation: 257
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
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
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
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 List
s and not other collection types as the ForEach extension method is defined for List
s.
Upvotes: 6
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
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