Reputation: 23
I am trying to zip 2 lists of lists of objects - only where the resulting zipped list would contain lists of distinct objects (list 2's lists sometimes have duplicate objects when compared to list 1). The count of objects in the resultant list must be maintained, meaning we can't have lists of differing sizes. The number of lists in list 1 is greater the number in list 2. Which would mean repeatedly going through list 2 when zipping.
The above is represented using loops below. Is this possible using only linq?
//this list of list contains the larger number of elements to which the 2nd list of list needs to be joined
List<List<object>> FullList = new List<List<object>>(); //is not empty - instantiated with some list
//2nd list of list - contains duplicates of the 1st list in terms of the objects in the underlying list
List<List<object>> comboBaseList = new List<List<object>>(); //is not empty - instantiated with some list
List<List<object>> comboList = comboBaseList;
//need to zip lists where there are no duplicate objects in the 2nd list's list, the count of the 1st list of list remains the same as FullList
List<List<object>> finalList = new List<List<object>>(); //empty - meant to hold final combined list
int i = 0;
foreach iList in FullList
{
if (i < comboList.count)
{
while (iList.Select(x => x.Id).Contains(comboList[i].Select(y => y.Id)))
{
i += 1;
}
finalList.Add(iList.Zip(comboList[i], (x, y) => x.Union(y))); //**CAN WE BYPASS THE LOOPS AND JUST USE LINQ?
comboList.RemoveAt(i);
i = 0;
}
else
{
comboList = comboBaseList;
i = 0;
}
}
To simplify the data I'll use lists of lists of integers - which could be the Id's of the objects in my case
FullList =
(
{1,2,3},
{2,5,6},
{7,8,9}
)
comboList =
(
{2,5},
{8,9}
)
I want to zip the above lists to yield the resultant as below - Note that there are 3 results as per FullList and the undelying lists have distinct integers
finalList =
{
{1,2,3,8,9},
{2,5,6,8,9},
{7,8,9,2,5}
}
Upvotes: 0
Views: 421
Reputation: 1499870
Okay, it sounds like you might want something like:
var result = fullList
.Select(original =>
// We want the original sublist...
original
// concatenated with...
.Concat(
// ... any comboList element
comboList
// which is completely distinct from "original"
.Where(cl => !original.Intersect(cl).Any())
// ... flattening all such comboLists
.SelectMany(cl => cl))
.ToList())
.ToList();
Here's a complete example:
using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
static void Main()
{
var fullList = new[]
{
new[] { 1, 2, 3 },
new[] { 2, 5, 6 },
new[] { 7, 8, 9 }
};
var comboList = new[]
{
new[] { 2, 5 },
new[] { 8, 9 }
};
var result = MergeCombinations(fullList, comboList);
foreach (var item in result)
{
Console.WriteLine(string.Join(", ", item));
}
}
static List<List<T>> MergeCombinations<T>(
IEnumerable<IEnumerable<T>> fullList,
IEnumerable<IEnumerable<T>> comboList)
{
var result = fullList
.Select(original =>
// We want the original sublist...
original
// concatenated with...
.Concat(
// ... any comboList element
comboList
// which is completely distinct from "original"
.Where(cl => !original.Intersect(cl).Any())
// ... flattening all such comboLists
.SelectMany(cl => cl))
.ToList())
.ToList();
return result;
}
}
Upvotes: 1
Reputation: 684
var fullList = new List<List<int>>()
{
new List<int>() {1,2,3},
new List<int>() {2,5,6},
new List<int>() {7,8,9}
};
var comboList = new List<List<int>>()
{
new List<int>() {2,5},
new List<int>() {8,9},
};
fullList.ForEach(i =>
{
comboList.ForEach(j =>
{
if (i.All(x => !j.Contains(x)))
{
i.AddRange(j);
return;
};
});
});
Upvotes: 0