Removal operation in List<string> - c#

I have 2 Lists of type string:
List1 has items - item1, item2, item3
List2 has items - item2, item3
Now I need to compare both lists and remove the duplicated items from List1. The modified List1 should have just one item, which is "item1".
foreach loops may work, but what I want to know is there any inbuilt method which does this?
EDIT
Thanks for the answers guys. I was just thinking what would be the case if I wanted to add the missed out items into the List. So just raised another question similar to this.
Add operation in List<string>
TIA!

I suspect the best approach to use here would be to put the second list into a hash first, i.e.
var hash = new HashSet<TheType>(List2);
List1.RemoveAll(hash.Contains);
This avoids having O(n*m) performance, instead being O(n+m)
Example:
List<int> List1 = new List<int> {1,2,3};
List<int> List2 = new List<int> {2,3};
var hash = new HashSet<int>(List2);
List1.RemoveAll(hash.Contains);
// now List1 just has {1}

You could use:
list1.RemoveAll(item => list2.Contains(item));
(As Marc says, this is O(N*M) - fine if you expect the lists to be very short, but awful if either of them could get big.)
Or if you don't mind it being a new list (rather than modifying the existing one), you could just use:
list1 = list1.Except(list2).ToList();

Use
List1 = List1.Except(List2).ToList();

I recommend using:
List1 = List1.Except(List2).ToList();

Related

How do I compare two lists where one list starts with the other, and only return the "overhang" elements?

I have two List<string>:
List 1:
snap
crackle
List 2:
snap
crackle
pop
bang
List 2 will always start with the same elements as List 1, but will always have some extra elements "hanging off the end." I want to return a list of just these "overhang elements."
So in the above example, I want a list of:
pop
bang
Is there a LINQ operator that does this?
You can use Except extension method:
var list1 = new List<string> { "snap", "crackle" };
var list2 = new List<string> { "snap", "crackle", "pop", "bang" };
var result = list2.Except(list1).ToList();
Ivan Stoev pointed that the solution above will produce the set difference. If you want the list difference and the second list always contains elements from the first list at the beginning you can use this solution:
var result = list2.Skip(list1.Count).ToList();
Run this example on .NET Fiddle.
You can use the Except() linq method to do this:
var onlyIn2 = list2.Except(list1);

Add mutliple Lists to one list

I have multiple functions that returns a List of objects. How can I add them into one list.
var List1 = GetList1().RunFilter1();
var List2 = GetList2();
The AddRange() function gets far to messy.
List1.AddRange(List2.AddRange(List3.AddRange(List4.AddRange(...);
Is there a pattern that I can use that it will be easier. I also have extension methods (Filters) that apply to certain lists. Which I interchange based on requirement.
Something like this:
var CombinedList = GetAllLists(GetList1().RunFilter1(),
GetList2(),
GetList3().RunFilter2(),
GetList4() ...);
Keep in mind that the GetList() functions being fetched might change.
Thanks for any help!
You can use some Linq extensions to help you out with the format a bit
var joined = GetList1()
.Concat(GetList2())
.Concat(GetList3().RunFilter())
...
;
You could first insert all your lists into another list:
var temp = new List<T>
{
GetList1().RunFilter1(),
GetList2(),
GetList3().RunFilter2(),
GetList4()
};
Then using the SelectMany method flatten this list.
var combined = temp.SelectMany(item=>item).ToList();

In C#, What is the best way to see if a list contains another list?

If i have a list of strings, what is the best way to determine if every element in another list is contains in this list. For example:
List<string> list = new List<string>();
list.Add("Dog");
list.Add("Cat");
list.Add("Bird");
List<string> list2 = new List<string>();
list.Add("Dog");
list.Add("Cat");
if (list.ContainsList(list2))
{
Console.Write("All items in list2 are in list1")
}
I am trying to determine if there something like this "ContainsList" method?
if (!list2.Except(list).Any())
Loved SLaks version. Just for completeness, you can use HashSet method IsSubsetOf when performing set operations (also check IsSupersetOf method). There are pros and cons for this approach. Next code shows an example:
var list1 = new HashSet<string>{ "Dog", "Cat", "Bird" };
var list2 = new HashSet<string>{ "Dog", "Cat" };
if (list2.IsSubsetOf(list1))
{
Console.Write("All items in list2 are in list1");
}
Except method is streaming in nature. In query list2.Except(list1) list1 is buffered completely into memory, and you iterate one item at a time through list2. IsSubsetOf works eagerly in the opposite manner. This starts to make a difference when you have huge sets of data.
To analyse the worst case performance, here is some code from Except implementation at Monos Enumerable (dotPeek gives very similar results, just less readable)
var items = new HashSet<TSource> (second, comparer); //list1.Count
foreach (var element in first) //list2.Count
if (items.Add (element)) //constant time
yield return element;
as result O(list1.Count + list2.Count), loops aren't nested.
IsSubset has next method call, if second IEnumerable is HashSet (decompiled via dotPeek):
private bool IsSubsetOfHashSetWithSameEC(HashSet<T> other)
{
foreach (T obj in this) //list2.Count
if (!other.Contains(obj)) //constant time
return false;
return true;
}
Resulting in O(list2.Count) if list1 is a HashSet.
How about,
var list1 = new List<string>{"Dog","Cat","Bird"};
var list2 = new List<string>{"Dog","Cat"};
if (list1.Union(list2).SequenceEqual(list1))
Console.Write("All items in list2 are in list1");
How about this
list1.intersect (list2).ToList ().Foreach ((x)=>
{
Console.Writeline (x)
});

comparing two Lists in C#

I have two Lists, and I've values in these as,
List1 List2
----- -----
1 1
2 2
3
I've to compare the second list with the first list, and I've to return the values which is not in the List1(here "3"), how can we compare two lists like this?
can anyone help me?
Use LINQ and the Except extension method.
var list1 = new List<int> { 1, 2 };
var list2 = new List<int> { 1, 2, 3 };
var remaining = list2.Except(list1);
Try this:
var result = list2.Except(list1);
Note that it's considered bad style to use initial capitals on your variable names (unless they're actually properties) :-)
Here you go: http://msdn.microsoft.com/en-us/library/bb300779.aspx
Rarest examples on msdn which i found useful.

C# list of lists - how to make list in lists unique and edition resistant?

this time I've got an C# programming issue:
I've got a list of lists:
List<List<string>> List1
And that list of strings in it:
List<string> List2
And, in loop, I want to put List2 in List1, but then, I want to change values in List2, but I don't want to change this values in the List2 which was inserted in List1.
Here is the example with pseudo-code of what I want to do (because I suppose nobody gets what I want at the moment):
List1 <=> ['one', 'two', 'three']
List2[1] <=> List1
List1.clear
List1 <=> ['four', 'five', 'six']
List2[2] <=> List1
but List1 changed in List2[1] too - I don't want that! It looks like now:
List2[1] <=> ['four', 'five', 'six']
List2[2] <=> ['four', 'five', 'six']
But I want that it will be:
List2[1] <=> ['one', 'two', 'three']
List2[2] <=> ['four', 'five', 'six']
What's the point? I want that these List1s stay in that state, what there were when I was inserting them to the List2. I hope someone will understand this and will help me.
I know that I'm inserting some kind of List1 pointners in List2, but how make it right? (right -> the way I want it to work^^)
You want to put a copy of List1 in List2:
List2[1] = List1.ToList();
Otherwise, List1, List2[1] and List2[2] reference the same list, so by changing one, you're also changing the others.
you need to create a new list for each item in the outer list. Remember, you are placing a reference to the inner list in the outer list, not a copy.
outerList.Add(new List<string>{"one", "two", "three"})
outerList.Add(new List<string>{"four", "five", "six"})
We understand. The reason List1 is "changing" is because List1 is a pointer to a place in memory where its items are stored. So when you assign List2[1] = List1, you're just creating another pointer called List2[1] to the same place in memory.
To accomplish what you're talking about, you'll have to create a new list each time you pass through the loop. So for example:
List two = new List<List<string>>();
for (int i = 0; i < 5; i++) {
List one = new List<string> {"one" + i, "two" + i, "three" + i};
two.Add(one);
}
In each pass through this loop, List one will be a new object. At the end, List two will have these values in it:
[["one1", "two1", "three1"], ["one2", "two2", "three2"], ... ]
You can generate the values any way you wish, but I was just showing an example of making them dynamic based on the loop counter.
Here's one answer I know. You have to do a deep-copy type of operation when you want to store a copy of a list rather than a reference to the original. Deep copy is unfortunately not part of the framework.
Via the commenter "karl" ( http://openmymind.net/ ) on the blog at http://weblogs.asp.net/jeff/archive/2005/11/21/431125.aspx with my own edits to add to the example... you can serialize and deserialize the list, and you get a true copy of the list:
List<string> strings = new List<string>();
// Do something to populate the list
BinaryFormatter bf = new BinaryFormatter();
MemoryStream ms = new MemoryStream();
bf.Serialize(ms, strings);
ms.Seek(0, SeekOrigin.Begin);
List<string> copy = (List<string>)bf.Deserialize(ms) ;
ms.Close();
Try to translate this page to understand: http://leonelfraga.com/neomatrixtech/?p=412
Note the code diferences and what is being printed in the dark boxes.
To achieve your desired result, you need to store a copy of the list you wish to modify. You can do this either by creating a new list and adding the elements from the original in manually, or by using the extension method ToList(...). This will create a copy of your original list, which will be stored, so you can then modify the original list without affecting the copy.

Categories

Resources