[英]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
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.