简体   繁体   English

搜索List的最佳方法是什么 <List<string> &gt;?

[英]What is the best way to search a List<List<string>>?

Say I have the following list: 说我有以下列表:

List 1:
{{"John", "Doe", "Tall", "Old"},
{"John", "Doe", "Short", "Old"},
{"Jane", "Doe", "Tall", "Young"},
{"Jane", "Doe", "Short", "Old"}}

And I want to search the list for {"John", "Doe", "Short", "Old"}. 我想在列表中搜索{“John”,“Doe”,“Short”,“Old”}。

What is the best way to search for this nested list entry and ensure I don't get {"John", "Doe", "Tall", "Old"} instead? 搜索此嵌套列表条目的最佳方法是什么,并确保我不会获得{“John”,“Doe”,“Tall”,“Old”}?

If the nested list contained only one string item instead of four, I would use LINQ to flatten the list and search the resulting List<string>. 如果嵌套列表只包含一个string项而不是四个,我将使用LINQ展平列表并搜索生成的List<string>. ie: 即:

List<string> newList = oldList.SelectMany(x => x).Distinct().ToList();
newList.Contains("string");

Is there something similar I can do for a list that contains more than one string item per each nested list? 我可以为每个嵌套列表包含多个字符串项的列表做些类似的事情吗?

So the list must contain all strings in that order? 那么列表必须包含该顺序中的所有字符串? Then you can use Enumerable.SequenceEqual . 然后你可以使用Enumerable.SequenceEqual If the order is not important use Enumerable.All with Contains , so: 如果订单不重要,请使用Enumerable.All with Contains ,所以:

var names = new[]{"John", "Doe", "Short", "Old"};
List<List<string>> result = list
    .Where(l => l.SequenceEqual(names)).ToList();

or 要么

result = list
    .Where(l => l.All(name => names.Contains(name))).ToList();

Output: 输出:

foreach(List<string> l  in result)
    Console.WriteLine(string.Join(",", l));  // John,Doe,Short,Old

Demo 演示

Side-note: you could make the second approach more efficient if you convert the collection you are searching to a HashSet<T> : 附注:如果将要搜索的集合转换为HashSet<T>则可以使第二种方法更有效:

var names = new HashSet<string>(new[]{"John", "Doe", "Short", "Old"});
result = list.Where(l => l.All(names.Contains)).ToList();

As Servy has mentioned, the second approach does not prevent you from getting lists that contain all the items but also more. 正如Servy所提到的,第二种方法并不能阻止你获得包含所有项目的列表,而且还有更多。 You could add a Count check to ensure it. 您可以添加Count检查以确保它。

您可以使用允许传递自定义相等比较器( IEqualityComparer<T> )的Contains方法的重载版本。

One way of "flattening" the list would be as follows: “扁平化”清单的一种方法如下:

var people = list1.
    Select(lst => new {
        First  = lst[0]
    ,   Last   = lst[1]
    ,   Height = lst[2]
    ,   Age    = lst[3]
    });

Now you can search for containment as follows: 现在您可以按如下方式搜索包含:

bool hasShortOldJohnDoe = people
    .Contains(p => p.First=="John"
                && p.Last=="Doe"
                && p.Height == "Short"
                && p.Age=="Old");

You can try the following: 您可以尝试以下方法:

List<List<string>> mainList = new List<List<string>>

{
    new List<string>(){"John", "Doe", "Tall", "Old"},
    new List<string>(){"John", "Doe", "Short", "Old"},
    new List<string>(){"Jane", "Doe", "Tall", "Young"},
    new List<string>(){"Jane", "Doe", "Short", "Old"},
};
List<string> searchList = new List<string>() { "John", "Doe", "Short", "Old" };

var temp = mainList[0].Except(searchList).Count();
List<List<string>> result  = mainList
                                .Where(r => r.Except(searchList).Count() == 0)
                                .ToList();

It will give you one item in the result . 它会在result给你一个项目。

Or: 要么:

var  result = mainList
                  .Where(r => !r.Except(searchList).Any());

Here is a couple of ways: 这有两种方法:

 [Test]
    public void Using_String_Join()
    {
        var l = new List<List<string>>
        {
            new List<string> {"John", "Doe", "Tall", "Old"},
            new List<string> {"John", "Doe", "Short", "Old"},
            new List<string> {"Jane", "Doe", "Tall", "Young"},
            new List<string> {"Jane", "Doe", "Short", "Old"}
        };

        var l2 = new List<string> {"John", "Doe", "Short", "Old"};

        Assert.That(l.Count(inner => string.Join(",", inner).Equals(string.Join(",", l2))), Is.EqualTo(1));
    }

    [Test]
    public void Using_SequenceEqual()
    {
        var l = new List<List<string>>
        {
            new List<string> {"John", "Doe", "Tall", "Old"},
            new List<string> {"John", "Doe", "Short", "Old"},
            new List<string> {"Jane", "Doe", "Tall", "Young"},
            new List<string> {"Jane", "Doe", "Short", "Old"}
        };

        var l2 = new List<string> {"John", "Doe", "Short", "Old"};

        Assert.That(l.Count(inner => inner.SequenceEqual(l2)), Is.EqualTo(1));
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM