list1 contains userid and username
list2 contains userids
Need to display the list1 where its userid is included in list2.
string userids = "user1,user2,user3";
var list2 = userids.Split(',').Select(userid => userid.Trim()).ToList();
list1 = list1.Any(x => x.UserID)... //Got stuck here
Better use HashSet<T> for search:
string userids = "user1,user2,user3";
var userIdSet = new HashSet<string>(userids.Split(',').Select(userid => userid.Trim()));
list1 = list1.Where(x => userIdSet.Contains(x.UserID)).ToList();
Another way is Enumerable.Join which is more efficient if the lists are pretty large:
var containedUsers = from x1 in list1
join x2 in list2 on x1.UserId equals x2
select x1;
list1 = containedUsers.ToList();
I assume that the UserID's in list2 are unique(otherwise use Distinct). If not, joining them might cause duplcicate items in list1.
Its easy to get stuck on So you need to check list2 contains the item you picked.
found = list1.Where( x => list2.contains(x.UserID));
Method Any returns bool, it
Determines whether any element of a sequence satisfies a condition
Return Value
Type: System.Boolean
true if any elements in the source sequence pass the test in the specified predicate; otherwise, false.
Method Where
Filters a sequence of values based on a predicate.
So you can use Any inside Where to filter only results that contains inside list2.
list1 = list1.Where(l1 => list2.Any(l2 => l2 == l1.UserID)).ToList();
References: Enumerable.Any(Of TSource) Method, Enumerable.Where(Of TSource) Method
Related
Hello I have these two Lists
List<string> list1 = {"404a49ad-d80f-4ef7-99ab-0996de3b70d4_29190_806.jpg|Name1", "404a49ad-d80f-4ef7-99ab-0996de3b70d4_29197_806.jpg|Name2", "404a49ad-d80f-4ef7-99ab-0996de3b70d4_29210_868.jpg|Name3"}
List<string> list2 = {"404a49ad-d80f-4ef7-99ab-0996de3b70d4_29190_806.jpg","404a49ad-d80f-4ef7-99ab-0996de3b70d4_29197_806.jpg"}
I want to intersect the values of list1 separating by '|' character, with the list2 values, but I want to return the full string of list1 and not only the first part separated by '|' character.
This is the result i want:
var finalList = {"404a49ad-d80f-4ef7-99ab-0996de3b70d4_29190_806.jpg|Name1", "404a49ad-d80f-4ef7-99ab-0996de3b70d4_29197_806.jpg|Name2"}
I dont know if its possible with the instersect function or there is another approach I can use. I've tried using Contains function in a predicate but it takes to much time to find the matches.
I'm using large lists with 2000 elements approx.
Thanks!
Try this, gives the expected results in LinqPad, using your example:
var intersection =
list1.Join(
list2,
l1 => l1.Split('|')[0], //Selector for items from the inner list splits on '|'
l2 => l2, //Select the current item
(l1, l2) => l1);
Compile list2 into a HashSet<string> to allow fast lookups. Then, use a simple Where filter to perform lookups of substrings from list1 against this set.
List<string> list1 = new List<string> { "404a49ad-d80f-4ef7-99ab-0996de3b70d4_29190_806.jpg|Name1", "404a49ad-d80f-4ef7-99ab-0996de3b70d4_29197_806.jpg|Name2", "404a49ad-d80f-4ef7-99ab-0996de3b70d4_29210_868.jpg|Name3" };
List<string> list2 = new List<string> { "404a49ad-d80f-4ef7-99ab-0996de3b70d4_29190_806.jpg", "404a49ad-d80f-4ef7-99ab-0996de3b70d4_29197_806.jpg" };
var list2HashSet = new HashSet<string>(list2);
var finalList = list1.Where(s => list2HashSet.Contains(s.Substring(0, s.IndexOf('|')))).ToList();
Note that s.Substring(0, s.IndexOf('|')) is semantically equivalent to s.Split('|')[0] (assuming that all your strings contain |), but avoids the overhead of allocating another string instance for the text behind the |.
Use where to iterate over the list. Use the Split method to get the first part you are interested in, and then check to see if list2 contains that string. Finally call ToList to convert the result to a list.
var finalList = list1.Where(x => list2.Contains(x.Split(new []{'|'})[0})).ToList();
My code
query1 = select value1, value2 from dbo.animal where animalname="tiger";
query2 = select value1, value2 from dbo.animal where animalname="lion";
List<Animal> list1 = db.ExecuteStoreQuery<Animal>(query1).ToList();
List<Animal> list2 = db.ExecuteStoreQuery<Animal>(query2).ToList();
// list1.Count = 1 list1[0].value1 = "a" list1[0].value2 = "b"
// list2.Count = 1 list2[0].value1 = "a" list2[0].value2 = "b"
// Now I would like to compare list1 and list2 to see if they are equal
var list3 = list1.Except(list2);
//At this point list3 is containing both list1 and list2 and using var made it
//GenericList not the same type of list as List1 and List2
I tried List list3 = list1.Except(list2) but I get compile error.
So the question is how do I find out if list1 is equal to list2?
I was hoping list3 would be the differences between list1 and list2 and therefore if the lists are equal list3.count() should be 0.
The nice thing about my data is I believe data in from query1 and query should be both in order and result in only 1 record each.
First of all, checking if the results of Except are empty cannot answer the "are these two lists equal?" question. It answers the "does list2 contain all the elements of list1?", which is not the same, because list2 may contain additional elements.
The nice thing about my data is I believe data in from query1 and query should be both in order and result in only 1 record each.
You can compare two identically ordered lists for equality using SequenceEqual, like this:
bool areIdentical = list1.SequenceEqual(list2);
If the ordering is different, you can also force it to be the same with OrderBy:
bool areIdentical = list1
.OrderBy(animal=>animal.Id)
.SequenceEqual(list2.OrderBy(animal=>animal.Id));
I'm new to C#.
I have the following struct.
struct Foo
{
string key;
Bar values;
}
I have two lists of Foo, L1 and L2 of equal size both contain same set of keys.
I have to merge the corresponding Foo instances in L1 and L2.
Foo Merge(Foo f1, Foo f2)
{
// merge f1 and f2.
return result.
}
I wrote the following to achieve this.
resultList = L1.Join(L2, f1 => f1.key, f2 => f2.key, (f1, f2) => Merge(f1, f2)
).ToList())
My problem is that my key is not unique. I have n number of elements in L1 with the same key (say "key1") (which are also appearing in L2 somewhere). So, the above join statement selects n matching entries from L2 for each "key1" from L1 and I get n*n elements with key "key1" in the result where I want only n. (So, this is kind of crossproduct for those set of elements).
I want to use Join and still select an element from L1 with "key1" and force the Linq to use the first available 'unused' "key1" element from L2. Is this possible? Is join a bad idea here?
(Also, the I want to preserve the order of the keys as in L1. I tried to handle all elements with such keys before the join and removed those entries from L1 and L2. This disturbed the order of the keys and it looked ugly).
I'm looking for a solution without any explicit for loops.
From your comment to ElectricRouge answer, you could do something like
var z = list1.Join(list2.GroupBy(m => m.Id),
m => m.Id,
g => g.Key,
(l1, l2) => new{l1, l2});
this would give you a list of all keys in l1, and the corresponding grouped keys in l2.
Not sure it's really readable.
I need to find the corresponding entries in two lists and do some operation on them. That is my preliminary requirement.
For this you can do something like this.
var z=S1.Select(i=>i.Key).Tolist(); //make a list of all keys in S1
List<Foo> result=new List<Foo>();
foreach(var item in z) // Compare with S2 using keys in z
{
var x=item.Where(i=>i.Key==item.Key)
result.Add(x);
}
Is this what you are looking for?
I want to use Join and still select an element from L1 with "key1" and force the Linq to use the first available 'unused' "key1" element from L2. Is this possible?
When combining elements from the two lists you want to pick the first element in the second list having the same key as the element in the first list. (Previously, I interpreted you question differently, and a solution to this different problem is available in the edit history of this answer.)
For quick access to the desired values in the second list a dictionary is created providing lookup from keys to the desired value from the second list:
var dictionary2 = list2
.GroupBy(foo => foo.Key)
.ToDictionary(group => group.Key, group => group.First());
The use of First expresses the requirement that you want to pick the first element in the second list having the same key.
The merged list is now created by using projection over the first list:
var mergedList = list1.Select(
foo => Merge(
foo,
dictionary2[foo.Key]
)
);
When you use foreach to iterate mergedList or ToList() the desired result will be computed.
You could use Union to remove the duplicated keys.
Documentation at http://msdn.microsoft.com/en-us/library/bb341731.aspx
List<int> list1 = new List<int> { 1, 12, 12, 5};
List<int> list2 = new List<int> { 12, 5, 7, 9, 1 };
List<int> ulist = list1.Union(list2).ToList();
Example taken from : how to merge 2 List<T> with removing duplicate values in C#
Or you can use Concat to merge a list of different types (Keeping all keys).
See the documentation her : http://msdn.microsoft.com/en-us/library/bb302894(v=vs.110).aspx
var MyCombinedList = Collection1.Concat(Collection2)
.Concat(Collection3)
.ToList();
Example taken from same question : Merge two (or more) lists into one, in C# .NET
Finally I adapted Raphaël's answer as below.
public class FooComparer : IEqualityComparer<Foo>
{
public bool Equals(Foo o1, Foo o2)
{
return o1.key == o2.key;
}
public int GetHashCode(Foo obj)
{
return obj.key.GetHashCode();
}
}
resultList = L1.Join(L2.Select(m => m).Distinct(new FooComparer()).ToList(), f1 => f1.key, f2 => f2.key, (f1, f2) => Merge(f1, f2)
).ToList());
Short explanation:
L2.Select(m => m).Distinct(new FooComparer()).ToList()
creates a new list by removing the duplicate keys from L2. Join L1 with this new list to get the required result.
Suppose I have a collection of strings.
How do I select all the elements that don't contain a certain parameter value?
List<string> TheList = .....
var TheCleanList = (from s in TheList
where s != parameter
select s).ToList();
I was thinking about where s!= parameter but I'm wondering if there's a cleaner way to do it.
Thanks.
If you don't need a new list you don't need Linq for this - use Remove()- this avoids having to create a new list:
If you want to remove all strings that are equal to Parameter:
TheList.RemoveAll(s => s == Parameter);
If you want to remove all strings that contain Parameter (not clear from your question):
TheList.RemoveAll(s => s.Contains(Parameter));
You mean:
List<string> TheList = .....
var TheCleanList = (from s in TheList
where !s.Contains(parameter)
select s).ToList();
You can use String.Contains
var TheCleanList = (from s in TheList
where !s.Contains(parameter)
select s).ToList();
Or
var TheCleanList = TheList.Where(s => !s.Contains(parameter)).ToList();
String.Contains is case-sensitive. If you want a case-insensitve:
string lower = parameter.ToLower();
...
where s.ToLower().Contains(lower)
lest say I have two lists
List1:
"Tom",
"Frank",
"Lacey"
List2:
"Frank",
"Tom"
what would be the query needed to show that Tom and Fran are being repeated?
The lists that I am trying to compare are very big and if I do something like:
var q = from a in List1
from b in List2
where a.Name == b.Name
select a;
this takes a long time.
To see what values are duplicated across lists, you can use
var results = list1.Intersect(list2);
If you were otherwise interested in matching the items and doing something with each, you could use Join
var results = from item1 in list1
join item2 in list2
on item1 equals item2
select new
{
// include what you want here
};
In your case, since you are dealing with a list of strings, Intersect seems like the appropriate course of action. If you were dealing with matching lists of objects on a common key, you might opt to join the lists and project the results.
You should use Intersect:
var items = List1.Intersect(List2); // Tom, Frank
You can use intersect:
List<string> list3 = list1.Intersect(list2).ToList();