我有一个List<List<string>>
,它看起来像这样:
[0]
[0]Elephant
[1]26
[2]Thailand
[1]
[0]Elephant
[1]40
[2]Thailand
[2]
[0]Ant
[1]2
[2]Australia
[3]
[0]Camel Red hump
[1]1
[2]Nigeria
我想找到在Camel
一词中找到的索引,例如:3。
int index= animals.FindIndex(r => r.Contains("Camel"));
但是,上面的代码返回-1。我该如何解决?
答案 0 :(得分:8)
不可复制:
using System;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
var animals = new List<List<string>>()
{
new List<string> { "Elephant", "26", "Thailand" },
new List<string> { "Elephant", "40", "Thailand" },
new List<string> { "Ant", "2", "Australia" },
new List<string> { "Camel", "1", "Nigeria" }
};
int index= animals.FindIndex(r => r.Contains("Camel"));
Console.WriteLine(index);
}
}
按预期打印3。 您在未显示给我们的代码中做错了。向我们展示失败的代码。 采用上面刚刚写的代码,它是一个完整的程序,您可以剪切并粘贴并执行该程序,然后对其进行修改,以演示您的错误。这样,您将找到该错误,或者编写一个程序,让其他人清楚该错误是什么。
更新:问题与所陈述的不同。 将来,请写出描述您实际遇到的问题的问题。这样一来,每个参与人员都不必浪费时间在看错问题上。
真正的问题是:
var animals = new List<List<string>>()
{
new List<string> { "Elephant", "26", "Thailand" },
new List<string> { "Elephant", "40", "Thailand" },
new List<string> { "Ant", "2", "Australia" },
new List<string> { "Camel red hump", "1", "Nigeria" }
};
我们希望基于查询字符串“ Camel”找到项目3。
这是您解决此问题的方法。首先,您针对单个字符串进行解决:
string test1 = "Foo Bar Blah";
string test2 = "Camel red hump";
我们想要什么?我们想知道“ Camel”是否出现在字符串中。这是通过string.Contains
完成的:
Console.WriteLine(test1.Contains("Camel")); // False
Console.WriteLine(test2.Contains("Camel")); // True
好的。我们可以解决单个字符串的问题。现在,为字符串列表解决问题:
var list1 = new List<string> { "Ant", "2", "Australia" };
var list2 = new List<string> { "Camel red hump", "1", "Nigeria" };
我们希望知道谓词string.Contains("Camel")
对于list1
或list2
的任何成员是否成立。因此,请使用Any
:
(请记住添加using System.Linq;
以使用Any
序列方法。)
Console.WriteLine(list1.Any(s => s.Contains("Camel")); // False
Console.WriteLine(list2.Any(s => s.Contains("Camel")); // True
很好,我们现在有一个谓词适用于字符串列表。现在,我们希望将其应用于字符串列表:
var index = animals.FindIndex(
list => list.Any(
s => s.Contains("Camel")));
// Prints 3
你看到我在那里做什么? 您应该使用的方法来攻击序列中的问题:首先解决单个元素上的问题,然后将该解决方案扩展到元素序列,然后将该解决方案扩展到序列中元素等。从简单的问题逐步发展为更困难的问题。
现在,所有Any
可能是使用错误的谓词。如果您有一只动物new List<string>{"Canada Goose", "123", "United States"}
和一只动物new List<string>{"Wolverine", "4567", "Canada"}
,则在寻找加拿大鹅时,有冒险搜寻Canada
并发现金刚狼的风险。首先,您可能不应该将此数据表示为List<List<string>>
。您应该这样做:
class Animal
{
public string Kind { get; }
public int Size { get; }
public string Country { get; }
public Animal (string kind, int size, string country)
{
this.Kind = kind;
... and so on.
现在您可以说:
var animals = new List<Animal>()
{
new Animal("Elephant", 26, "Thailand"),
new Animal("Elephant", 40, "Thailand"),
new Animal("Ant", 2, "Australia"),
new Animal("Camel red hump", 1, "Nigeria")
};
现在您的测试是:
int index = animals.FindIndex(a => a.Kind.Contains("Camel"));
这更容易理解。 构建代表业务领域中概念的类型。这样一来,您就可以构建看起来像代码中的概念而不是机制的程序。
答案 1 :(得分:1)
所以您想知道列表的某些项目中是否存在字符串的一部分?
int index = animals.FindIndex(r=>r.Any(x=>x.Contains("Camel")));
仅说明一下,您的代码正在搜索完全匹配,但您没有相同的字符串。因此,此答案将搜索第一个列表(FindIndex
)的索引,其中至少一个元素(Any
)包含(Contains
)字符串Camel
。请注意,该代码区分大小写。
答案 2 :(得分:1)
@EricLippert答案与往常一样是正确的,但让我尝试多重构一下您的代码。
您有一个字符串列表列表,并且子列表始终包含:
0
上是一只动物1
上,一个ID 2
上,是一个国家。如果列表中的每个条目都是这种情况,那么最好使用类来抽象:
public class MyItem
{
public int Id { get; set; }
public string Animal { get; set; }
public string Country { get; set; }
}
然后,您可以将List<List<string>>
替换为更有用的类型:List<MyItem>
。
这样,您可以正确使用linq,例如:
var item = list.First(i => i.Animal.Contains("Camel"));
使用此策略,您无需获取项目索引,之后便需要获取其他值。