How to combine two separate IQueryable<string> collections into one? - c#

I have 2 separate collections.
IQueryable<string> customers;
IQueryable<string> customersPhone
Currently, this is the code I am using to join one with the other
IEnumerable<string> union = customers.Union(customersPhone);
The problem is that when I have multiple like records in the customers collection, the union is causing only a single record to be returned. I need to return all, regardless of duplicates, and join them with the customersPhone collection.
Is this possible? Does that make sense?
Thanks!
Kevin

You're looking for Concat(), which preserves duplicates.

you could try one of the 2 options below List one is customers in your case list2 would be customerPhone make the corrections to fit your Use Case
IQueryable customers;
IQueryable customersPhone
var list1 = list1.Concat(customers);
or
var list4 = list1.Union(customersPhone);

Related

Linq select objects by comparing from two lists of type int

I have a List<Organisation> Organisations.
Each Organisation has a property List<int> Categories.
I also have a separate List<int> DisplayCategories
I want to create a new List<Organisation> called DisplayOrganisations.
DisplayOrganisations will contain Organisation's whos Categories appear in my List<int> DisplayCategories.
How can I achieve this using linq or lambda?
The following is incorrect:
DisplayOrganisations = (from o in Organisations
where o.Categories.Intersect(DisplayCategories.CategoryIds)
select o).ToList();
I get an error:
Cannot implicitly convert type
'System.Collections.Generic.IEnumerable' to 'bool'
I believe that this is because I am selecting Organisations who's sub list of Categories need to be compared to a separate list DisplayCategories.
Any ideas?
Sure intersect will not give a boolean. you may want to check if there is any elements exist in it use Any.
DisplayOrganisations = Organisations
.Where(o => o.Categories.Intersect(DisplayCategories.CategoryIds)
.Any()).ToList();
Or better approach.
DisplayOrganisations = Organisations.Where(o => o.Categories
.Any(xDisplayCategories.CategoryIds.Contains)).ToList();
As you can see in the image Intersect uses hashset which is faster than second approach because Hashset has time complexity of O(1) for both adding and removing items. So in general Intersect is O(n+m). but the second approach using Any and Contains had time complexity of O(n^2) which could become much slower.Thanks to Dmitry Dovgopoly.
If you need only those Organisations where all elements are in CategoryIds list you can use mixture of Except() and Any() methods :
var DisplayOrganisations = Organisations.Where(o =>
!o.Categories.Except(DisplayCategories.CategoryIds).Any()).ToList();
If you just want to check that there is at least one id in the list of ids you can use .Any method :
var DisplayOrganisations = Organisations.Where(o => o.Categories
.Any(DisplayCategories.CategoryIds.Contains)).ToList();

Linq query run over list of parameters

I have a requirement to create a linq query that selects data from a database table where a certain functional result is true.
I am using linq-to-sql and the function works well and I can write a basic query to get the data.
My issue is that I have an in-memory list of parameters and I essentially need to run the linq query multiple times (once for every parameter list item) and aggregate the results.
I have tried using the .Any() as a join but linq doesn't like joining non-database result sets with database result sets.
Some Sample Code:
Parameter list: // lets call it "l"
{
One,
Two,
Three
}
Query
From w in words where funcWord(l.item) == true select w;
So I would require a query that can run the above query once for every item in l and aggregate the results.
Any help is appreciated.
Thanks.
Multiple from statements will go through every combination, sort of like nested foreach statements:
from item in list
from w in words
where funcWord(item, w.name) == true
select w;
Interestingly, this gets translated to a SelectMany statement that is similar to Arithmomaniac's answer.
Try SelectMany, which aggregates the result of a one-to-many function, applied to each member.
In this case, the members are the elements of list, and the one-to-many function is your above, l-dependent query (though I rewrote it as a lambda function.)
list.SelectMany(l => words.Where(w => funcWord(l.item, w.name)));

Need help joining two lists of objects in C#

With my two lists of objects, I want to keep the total set of unique items based on a string key, where any collisions come from the first list, and any misses come from the second. Stated differently, I want to ignore any items in the first list that are not in the second list, but I want to keep all items that do exist in the second list as well as any remaining items from the second list.
What's the best way to do this?
Edit: This problem is more subtle than a simple union. A union will join the distinct items from two lists. In the case of a collision it takes the item from the outer list.
In my case, I have some items in List1 that I don't want to keep because they don't exist in List2, while I do want to keep all items from list 2.
Is there a cleaner / shorter way to do the below?
var remaining = allowedItems.Except(recentItems)
var allowedRecentItems = recentItems.Intersect(allowedItems)
var result = allowedRecentItems.Concat(remaining);
Try this:
var resultlist = list1.Union(list2);
var list1 = new List<string>{"A", "B", "C"};
var list2 = new List<string>{"B", "C", "D"};
var list = list1.Union(list2);
If I understood it correctly - You should keep the second list only. By that your both conditions are fulfilled
I want to ignore any items in the first list that are not in the second list
off-course if you keep the second list only then all the items in the first list which are not present in the second list will automatically be ignored.
I want to keep all items that do exist in the second list as well as any remaining items from the second list
On the other hand, the items present in both of the lists will automatically be selected including those which are only present in the second list.
If that's not what you want then you should check List.Distinct(), List.Except() and List.Union() extension methods.
Using the second list just do the trick. Directly translating your your requirements produces:
list1.Intersect(list2).Union(list2) which results list2

Can i Union 3 ToSelectList

I have three seperate ToSelectList items and i wanted to combine each list into one dropdown list box and was wondering if i could use a Union for it. Or is it that a union is only for 2 toselectlist items only.
Thanks!
When item exists in more than one list, do you want item to appear once, or as many times as they exists in all lists?
As I understand you want just concat:
var combinedList = list1.Concat(list2).Concat(list3).ToList();
If you want to avoid duplicates:
var unionList = list1.Union(list2).Union(list3).ToList();
Union is more expensive, as it has to go through the list and take care of duplicates.
If your item is a reference type and there is no IComparable or IEquable interfaces and you don't provide IEqualityComparer, you likely don't need Union.
You can only union two lists at a time using Union() - but you can chain it to achieve what you want:
var resultList = list1.Union(list2).Union(list3).ToList();
You can try using the Union() linq extension method.
var finalSelectList = model.getFirstList().ToSelectList().Union(
model.getSecondList().ToSelectList().Union(
model.getThirdList().ToSelectList()))

best way to use LINQ to query against a list

i have a collection
IEnumerable<Project>
and i want to do a filter based on project's Id property to included any id that is in a list:
List<int> Ids
what is the best way to do a where clause to check if a property is contained in a list.
var filteredProjectCollection = projectCollection.Where(p => Ids.Contains(p.id));
You may be able to get a more efficient implementation using the Except method:
var specialProjects = Ids.Select(id => new Project(id));
var filtered = projects.Except(specialProjects, comparer);
The tricky thing is that Except works with two collections of the same type - so you want to have two collections of projects. You can get that by creating new "dummy" projects and using comparer that compares projects just based on the ID.
Alternatively, you could use Except just on collections of IDs, but then you may need to lookup projects by the ID, which makes this approach less appealing.
var nonExcludedProjects = from p in allprojects where Ids.Contains(p => p.Id) select p;
If you're going to use one of the .Where(p=> list.Contains(p)) answers, you should consier first making a HashSet out of the list so that it doesn't have to do an O(n) search each time. This cuts running time from O(mn) to O(m+n).
I'm not sure that I understand your question but I'll have a shot.
If you have: IEnumerable enumerable,
and you want to filter it such that it only contians items that are also present in the list: List list,
then: IEnumerable final = enumerable.Where(e => list.Contains(e));

Categories