I've been looking for something like that for days. I'm trying to remove all the elements from a bigger list A according to a list B.
Suppose that I got a general list with 100 elements with differents IDS and I get another list with specific elements with just 10 records. I need remove all the elements from the first list that doesn't exists inside the second list.
I'll try to show the code that I actually don't know how it didnt works.
List<Obj> listA = new List<Obj>();
List<Obj> listB = new List<Obj>();
//here I load my first list with many elements
//here I load my second list with some specific elements
listA.RemoveAll(x => !listB.Contains(x));
I don't know why but it's not working. If I try this example with a List<int> type, it works nicely but I'd like to do that with my object. This object got an ID but I don't know how to use this ID inside the LINQ sentence.
You need to compare the IDs:
listA.RemoveAll(x => !listB.Any(y => y.ID == x.ID));
List(T).RemoveAll
I believe you can use the Except Extension to do this.
var result = listA.Except(listB)
Reference: http://www.dotnetperls.com/except
If you want to remove a list of objects (listB) from another list (listA) use:
listA = listA.Except(listB).ToList()
Remember to use ToList() to convert IEnumerable<Obj> to List<Obj>.
who ever is viewing this now.I think var result = listA.Intersect(listB) will give the result for common values in the both the list.
According to the documentation on MSDN ( http://msdn.microsoft.com/en-us/library/bhkz42b3.aspx ), contains uses the default Equality comparer to determine equality, so you could use IEquatable's Equals method on your Obj class to make it work. HiperiX mentions the ref comparison above.
How to add the IEquateable interface: http://msdn.microsoft.com/en-us/library/ms131190.aspx
Related
I'm looking for a LINQ function that returns a list of unique strings from a list of objects which contain these strings. The strings of the objects are not unique. Like this:
List before:
name="abc",value=3
name="xyz",value=5
name="abc",value=9
name="hgf",value=0
List this function would return:
"abc","xyz","hgf"
Does such a function even exist? Of course I know how I could implement this manually, but I was curious if LINQ can do this for me.
var foo = list.Select(p => p.name).Distinct().ToList();
You could use the Distinct extension method. So basically you will first project the original objects into a collection of strings and then apply the Distinct method:
string[] result = source.Select(x => x.name).Distinct().ToArray();
(from object in objectList
select object.name).Distinct();
What is the best route to compare 2 List<MyClasses>?
List 2 could contain more values than List 1 which is ok. Just need to make sure List 2 contains everything in List 1. They also won't be in the same order.
You can use Except to find the set difference of two collections.
var hasAllItems = !list2.Except(list1).Any();
The simplest approach is to use Except (in your case, you don't care about the order of your elements in the lists):
var elementsInList2NotInList1 = list2.Except(list1);
Remember that this method uses a default equality comparer to compare the values. If you do care about the ordering of the elements, you'll need to do extra work, in order to check how each element of a list is equal to an element of the other list. The extra work would be the following:
Create your own comparer, implementing the interface IEqualityComparer;
Create your own Equals() and GetHashCode() methods for your custom data type.
One way to do it:
List1.All(o => List2.Contains(o));
This says "return true if and only if every item in list 1 is contained in list 2"
This will let you know if list2 does not contain an item that is in list1:
list1.Any(x => !list2.Contains(x));
You could put it in a variable so you don't have to think about the double negatives:
var list2ContainsList1 = !list1.Any(x => !list2.Contains(x));
I would like to create a list variable of items from another list. So lets say I have a list of 100 items I would like to pull items 25 - 35 and put them inside of another list. is there a way of doing this without calling a big for statement and pulling out the element one by one and putting that into a list.
you can use .Skip and .Take from System.Linq ....
Like this:
var result = myList.Skip(24).Take(10);
and if you need use ToList on the result to get another list
For a List<T>, you can use the GetRange Method.
Creates a shallow copy of a range of elements in the source List(Of
T).
Do note that the second argument represents the count of elements in the range, not the end-index of the range.
Since you mention ArrayList, I should point out that while it too has a GetRange, method, the type is considered essentially legacy since .NET 2.0.
Use both Take and Skip
var newList = oldList.Skip(25).Take(10);
I have list of objects I need to sort based on some of their properties. This works fine to sort it by one field:
reportDataRows.Sort((x, y) => x["Comment1"].CompareTo(y["Comment1"]));
foreach (var row in reportDataRows) {
...
}
I see lots of examples on here that do this with only one field. But how do I sort by one field, then another? Or how about a list of many fields? It seems like using LINQ orderby thenby would be best, but I don't know enough about it to know how use it.
For the parameters, something like this that supports any number of fields to sort by would be nice:
var sortBy = new List<string>(){"Comment1","Time"};
I don't want to be writing code to do this in every one of my apps. I plan on moving this sort code to the class that holds the data so that it can do more advanced things like using a list of parameters and implicitly recognizing that the field is a date and sorting it as a date instead of a string. The reportDataRow object contains fields with this information, so I don't have to do any messy checks to find out if the field is supposed to be a date.
Yes, I think it makes more sense to use OrderBy and ThenBy:
foreach (var row in reportDataRows.OrderBy(x => x["Comment1"]).ThenBy(x => x["Comment2"])
{
...
}
This assumes the other thing you want to order by is "Comment2".
Try this:
reportDataRows.Sort((x, y) =>
{
var compare = x["Comment1"].CompareTo(y["Comment1"]);
if(compare != 0)
return compare;
return x["Comment2"].CompareTo(y["Comment2"]);
});
You may want to look at this previous answer where I posted an extension method which handles multiple order by's in LINQ. This allows this sort of syntax:
myList.OrderByMany(x => x.Field1, x => x.Field2);
Look at the example for ThenBy on msdn.
If you're comparing your own objects, then you can implement the IComparable interface.
Otherwise, you can use the IComparer interface.
Using LINQ method syntax:
var sortedRows = reportDataRows.OrderBy(r => r["Comment1"])
.ThenBy(r => r["AnotherField"];
foreach (var row in sortedRows) {
...
}
And even more readable using query comprehension syntax:
var sortedRows = from r in reportDataRows
orderby r["Comment1"], r["Comment2"]
select r;
foreach (var row in sortedRows) {
...
}
You got it. Enumerable.OrderBy().ThenBy() is your ticket. It works exactly like it looks; elements are sorted by each projection, with ties decided by comparing the next projection. You can chain as many ThenBys as you want, and there are also OrderByDesc and ThenByDesc methods that will sort that projection in descending order.
As Albin has pointed out, An OrderBy chain does not touch the original list unless you assign the result of the ordering back to the original variable, like this:
reportDataRows = reportDataRows.OrderBy(x=>x.Comment1).ThenBy(x=>x.Comment2).ToList();
As a rule, OrderBy will perform slightly slower than List.Sort(); the algorithm is designed to work on any IEnumerable series of elements, so in order to sort (which requires knowing every element of the series) it slurps its entire source enumerable into a new array. However, OrderBy has a distinct advantage over Sort in that it is a "stable" sort; elements that are exactly equal to each other will retain their "relative order" in the sorted enumerable (the first of the two that you;d encounter when iterating through the unsorted list will be the first of the two encountered when iterating through the sorted list).
I'm currently working my way through the learning curve that is LINQ and I could really use some assistance. I don't know if what I want is possible, but if I had to wager, I bet it is.
I currently have a list of objects called _tables and each of these objects has within it another list of objects exposed through the property, "Indexes". Essentially, I'd like to end up with one List that contains all the Indexes from all of the _tables.
Here's what I have so far:
var indexes = from TableInfo tab
in _tables
where tab.Indexes.Count > 0
select tab.Indexes;
Unfortunately, this seems to be giving me another List of Lists, but only where the Indexes List contains more than one value... Is there some way to get all of these lists together without loops?
You want to use the SelectMany extension method.
_tables.SelectMany(t => t.Indexes)
In addition to tbischel's answer, the query expression version of what you're going for is below.
var indexes = from TableInfo tab in _tables
from index in tab.Indexes
select index;
You don't need the where clause and you also shouldn't need to tell it what tab is
And you will need to use SelectMany
var indexes = (from tab in _tables).SelectMany(t => t.Indexes)
Or you could do it like this
var indexes = from tab in _tables
from t in tab.Indexes
select t;
That should be a little more familiar syntaz
var rows = from item in table select item;