Convert paired lists into one-to-many lookup
-
14-07-2021 - |
문제
I have lists (of equal length) of paired strings, call them "source" and "target". One source may map to multiple targets. Can I convert this to a lookup table (mapping a source to a list of targets) using LINQ? One (long-winded) way of doing this is:
// There may be multiple targets corresponding to each source
// as in the following example lists.
// NB. Lists are guaranteed same length
List<string> sourceNames = new List<string>() { "A", "B", "C", "A", "B", "C" };
List<string> targetNames = new List<string>() { "Z", "Y", "X", "W", "V", "U" };
// Use extension methods to make list of unique source names
List<string> uniqueSourceNames = sourceNames.Distinct().ToList<string>();
// For each unique source, make a list of the corresponding targets
Dictionary<string, List<string>> nameLookup = new Dictionary<string, List<string>>();
foreach (string sourceName in uniqueSourceNames)
{
List<string> targetsForSource = new List<string>();
for (int index = 0; index < sourceNames.Count; index++)
{
if (sourceNames[index] == sourceName)
targetsForSource.Add(targetNames[index]);
}
nameLookup.Add(sourceName, targetsForSource);
}
// Can now use the nameLookup dictionary to map a source name to a list of target names
// e.g. this returns "Z", "W"
List<string> targets = nameLookup["A"];
Is there a way to do this more efficiently using LINQ?
해결책
You can use Zip and ToLookup:
var nameLookup = sourceNames
.Zip(targetNames, (x, y) => new { Source = x, Target = y })
.ToLookup(x => x.Source, x => x.Target);
다른 팁
You can use GroupBy
and ToDictionary
:
var lookup = sourceNames
.Select((Source, i) => new { Target = targetNames.ElementAt(i), Source})
.GroupBy(x => x.Source)
.ToDictionary(g => g.Key, g => g.Select(x => x.Target));
Now every distinct source-string is mapped to an IEnumerable<string>
targets.
foreach (var kv in lookup)
Console.WriteLine("{0} has destinations {1}"
, kv.Key
, string.Join(",", lookup[kv.Key]));
Edit: Here's the demo: http://ideone.com/b18H7X
제휴하지 않습니다 StackOverflow