BrainsOverFlow
BrainsOverFlow

Reputation: 25

Extract common between List<List<string>> and List<string> - C#

I have a List<List<string>> Full, build up by

for(...){
Full.Add(new List<string>());
Full[ListIndex].Add(string1);
Full[ListIndex].Add(string2);
Full[ListIndex].Add(string3);
...
}

can be read by

string2 = Full[sublistX][element1];

A List<string> Strings contain some of the instance for string2

I want to create a new List<List<string> NewList only contain sublist from Full[sublistX][element1] which equals to any element in List<string>Strings

For example,

List<List<string>> Full = new List<List<string>>()
{
    new List<string>() { "11", "AA", "!!", },
    new List<string>() { "22", "BB", "@@", },
    new List<string>() { "33", "CC", "##", },
    new List<string>() { "44", "DD", "$$", },
};

List<string> Strings = new List<string>()
{
    "AA", "DD",
};

I want the List<List<string> NewList contain:

sublist0: "11", "AA", "!!"; //match "AA"
sublist1: "44", "DD", "$$"; //match "DD"

For now, I'm probably doing this in a stupid way (hardcoded)

List<List<string>> Full;
List<string> Strings;
List<List<string>> NewList;

for (int i = 0; i < Full.Count; i++)
{
    if (Strings.Contains(Full[i][4]))
    {
        NewList.Add(new List<string>());
        NewList[ListIndex].Add(Full[i][0]);
        NewList[ListIndex].Add(Full[i][1]);
        NewList[ListIndex].Add(Full[i][2]);
        NewList[ListIndex].Add(Full[i][3]);
        NewList[ListIndex].Add(Full[i][4]);
        NewList[ListIndex].Add(Full[i][5]);
        NewList[ListIndex].Add(Full[i][6]);
        NewList[ListIndex].Add(Full[i][7]);
        NewList[ListIndex].Add(Full[i][8]);
        NewList[ListIndex].Add(Full[i][9]);
        ListIndex++;
    }
}

My question is: is there a better way to do it?

I think there could be two points that need optimizing:

  1. Avoid using for() to traverse the whole list "Full," especially when "Full" contains a lot of sublists and "Strings" only have little elements.
  2. From the code you can see I now have 10 elements in each sublist, and that could be increased/decreased in the future, but I hard coded the NewList[ListIndex].Add from index 0 to 9. Is there a way to get the counts of sublist elements? So that I can use for(sublist elements count) to add the NewList.

Upvotes: 1

Views: 93

Answers (4)

Firo
Firo

Reputation: 30813

List<List<string>> full = ...;
List<string> searchItems = ...;

// only filtering
var result = full.Where(l => searchItems.Any(l.Contains)).ToList();

// also copying
var result = full.Where(l => searchItems.Any(l.Contains)).Select(l => l.ToList()).ToList();

// or faster for big lists
var searchItemsSet = new HashSet<string>(searchItems);
var result = full.Where(list => list.Any(searchItemsSet .Contains)).ToList();

Upvotes: 2

Eldar
Eldar

Reputation: 10790

Well, you can utilize Linq as follows :

var filteredList = Full.Where(strs => strs.Any(s=> Strings.Contains(s))).ToList();

This will give you a list that includes any list that Full at least has one element contained by Strings list.

Fiddle

Upvotes: 2

Enigmativity
Enigmativity

Reputation: 117084

I feel that this reads a little nicer:

List<List<string>> NewList =
(
    from xs in Full
    where xs.Any(x => Strings.Any(s => x.Contains(s)))
    select xs
).ToList();

Upvotes: 1

Tim Schmelter
Tim Schmelter

Reputation: 460158

You can use Intersect...Any:

List<List<string>> resultList = FullLIst
    .Where(list => strings.Intersect(list).Any())
    .ToList();

This performs better than Contains if the lists are big.

Upvotes: 2

Related Questions