我正在将Listview项目与Generic List项目与 List.Any 方法进行比较,如下所示:
foreach (ListViewItem itemRow in lstviewAddsheets.Items)
{
if (InvalidSheets.Any(x => x != null && x.FilePath == itemRow.Tag.ToString()))
{
//Math found
}
}
请告诉我,如何获得与 itemRow.Tag.ToString()匹配的InvalidSheets列表索引。
答案 0 :(得分:5)
你可以这样做
int index = InvalidSheets.FindIndex(x => x != null && x.FilePath == itemRow.Tag.ToString());
如果您想直接获取对象,请执行此操作
var matchedObject = InvalidSheets.FirstOrDefault(x => x != null && x.FilePath == itemRow.Tag.ToString());
答案 1 :(得分:4)
由于使用List.FindIndex()
代替Linq查找索引的速度有多快,似乎存在争议,我写了一个测试程序。
这假设您只关心查找列表中第一个匹配项的索引。它不处理多个匹配项。
另请注意,此测试是最糟糕的情况,因为匹配项位于列表的最后。
我的x86发布版本的结果(在Windows 8 x64,四核处理器上运行):
Calling Via FindIndex() 100 times took 00:00:00.9326057
Calling Via Linq 100 times took 00:00:04.0014677
Calling Via FindIndex() 100 times took 00:00:00.8994282
Calling Via Linq 100 times took 00:00:03.9179414
Calling Via FindIndex() 100 times took 00:00:00.8971618
Calling Via Linq 100 times took 00:00:03.9134804
Calling Via FindIndex() 100 times took 00:00:00.8963758
显示List.FindIndex()
大约比使用Linq快四倍。
这是测试代码:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
namespace Demo
{
class Test
{
public string FilePath;
}
class Program
{
private void run()
{
int count = 1000000;
List<Test> list = new List<Test>(count);
for (int i = 0; i < count; ++i)
list.Add(new Test{ FilePath = i.ToString()});
string target = (count-1).ToString();
for (int trial = 0; trial < 4; ++trial)
{
Action viaFindIndex =
(
() =>
{
int index = list.FindIndex(x => (x != null) && (x.FilePath == target));
}
);
Action viaLinq =
(
() =>
{
int index = list.Select((x, i) => new { Item = x, Index = i })
.First(x => (x != null) && (x.Item.FilePath == target))
.Index;
}
);
viaFindIndex.TimeThis("Via FindIndex()", 100);
viaLinq.TimeThis("Via Linq", 100);
}
}
private static void Main()
{
new Program().run();
}
}
static class DemoUtil
{
public static void TimeThis(this Action action, string title, int count = 1)
{
var sw = Stopwatch.StartNew();
for (int i = 0; i < count; ++i)
action();
Console.WriteLine("Calling {0} {1} times took {2}", title, count, sw.Elapsed);
}
}
}
因此,假设List.FindIndex()
比使用Linq更快且更容易阅读,我认为没有理由使用Linq来解决这个特定问题。
int index = list.FindIndex(x => (x != null) && (x.FilePath == target));
与
int index = list.Select((x, i) => new { Item = x, Index = i })
.First(x => (x != null) && (x.Item.FilePath == target))
.Index;
第一个版本在所有方面获胜IMO。
答案 2 :(得分:3)
以下是获取索引的方法:
var index = InvalidSheets.Select((x, i) => new {Item = x, Index = i})
.First(x => x.Item != null && x.Item.FilePath == itemRow.Tag.ToString())
.Index;
但是,您可能希望使用FirstOrDefault
重构此内容:
foreach (ListViewItem itemRow in lstviewAddsheets.Items)
{
var sheet = InvalidSheets.Select((x, i) => new {Item = x, Index = i})
.FirstOrDefault(x => x.Item != null && x.Item.FilePath == itemRow.Tag.ToString());
if (sheet != null)
{
var index = sheet.Index;
}
}
答案 3 :(得分:1)
试试这个:
InvalidSheets.IndexOf(InvalidSheets.First(x => x != null && x.FilePath == itemRow.Tag.ToString()))
它将获得与谓词匹配的第一个无效表的索引
答案 4 :(得分:0)
您可以使用重载来投影索引,因此您需要选择匿名类型:
var invalids = InvalidSheets.Select((s, i) => { Sheet=s, Index=i })
.Where(x => x.Sheet != null && x.Sheet.FilePath == itemRow.Tag.ToString()));
bool anyInvalid = invalids.Any(); // is any invalid
IEnumerable<int> indices = invalids.Select(x => x.Index);// if you need all indices