Reputation: 329
I'm new to C# and need some help with comparing collections. I have two List<string>
collections with their contents as below:
Collection Old: {"AAA","BBB","CCC"}
Collection New: {"BBB","CCC","DDD"}
I want to get a collection like below:
Collection Final: {"AAA", "Remove"; "BBB", "Keep"; "CCC", "Keep"; "DDD", "Add"}
How can I do this?
Upvotes: 3
Views: 784
Reputation: 73311
If you have this method
public static IEnumerable<T> Concat<T>(params IEnumerable<T>[] sequences)
{
return sequences.SelectMany(x => x);
}
you should be able to write:
static readonly string Remove = "Remove";
static readonly string Keep = "Keep";
static readonly string Add = "Add";
var result = Concat
(
old.Except(new).Select(x => new { x, Remove }),
old.Intersect(new).Select(x => new { x, Keep }),
new.Except(old).Select(x => new { x, Add })
);
Of course you can use the built-in Enumerable.Concat
method but I find mine more elegant.
Upvotes: 0
Reputation: 41589
In 1 line (sort of)!
string[] colOld = {"AAA","BBB","CCC"};
string[] colNew = {"BBB","CCC","DDD"};
dynamic colALL = (from o in colOld.Union(colNew)
select new {Value = o, Action =
colOld.Any(s => s == o) ?
colNew.Any(s => s == o) ? "Keep" : "Remove"
: "Add"
}).ToList();
Note: This is a developer fusion conversionof the below vb.net which does work - I've not had chance to test the c# version:
Dim colOld() As String = {"AAA", "BBB", "CCC"}
Dim colNew() As String = {"BBB", "CCC", "DDD"}
Dim colALL = (From o As String In colOld.Union(colNew) _
Select New With {.Value = o, .Action = _
If(colOld.Any(Function(s) s = o), _
If(colNew.Any(Function(s) s = o), "Keep", "Remove"), _
"Add")}).ToList
Upvotes: 0
Reputation: 6851
var oldList = new List<String>() {"AAA", "BBB", "CCC"};
var newList = new List<String>() {"BBB", "CCC", "DDD"};
var diffDictionary = new Dictionary<string, string>();
foreach (var oldEntry in oldList)
{
diffDictionary.Add(oldEntry, "Remove");
}
foreach (var newEntry in newList)
{
if (diffDictionary.ContainsKey(newEntry))
{
diffDictionary[newEntry] = "Keep";
}
else
{
diffDictionary.Add(newEntry, "Add");
}
}
foreach (var dDico in diffDictionary)
{
Console.WriteLine(string.Concat("Key: ", dDico.Key, " Value: ", dDico.Value));
}
Upvotes: 1
Reputation: 24212
You can use a dictionary to do this...
at the end, each element in the dictionary will tell you how many items of each kind were removed or added.
It will indicate this with a count, not a simple 3 state flag... that is because you may have added or removed repeated items... what if you insert 3 AAA
's in the second collection.
string[] col1 = new string[] { "AAA", "BBB", "CCC" };
string[] col2 = new string[] { "BBB", "CCC", "DDD" };
Dictionary<string, int> colDic = new Dictionary<string, int>();
foreach (var item in col1)
{
int num;
if (colDic.TryGetValue(item, out num))
colDic[item] = num - 1;
else
colDic[item] = -1;
}
foreach (var item in col2)
{
int num;
if (colDic.TryGetValue(item, out num))
colDic[item] = num + 1;
else
colDic[item] = 1;
}
The end result will look like this:
AAA = -1
BBB = 0
CCC = 0
DDD = 1
Upvotes: 0
Reputation: 42013
old.Except(new)
will give you those items to remove
new.Except(old)
will give you items to add
old.Intersect(new)
will give you items to keep
(This is assuming you don't mind using the System.Linq namespace)
Or if you prefer, you can consider each item individually and check the existence in each list
Upvotes: 8