有没有更好的方法?
string[] s = {"zero", "one", "two", "three", "four", "five"};
var x =
s
.Select((a,i) => new {Value = a, Index = i})
.Where(b => b.Value.StartsWith("t"))
.Select(c => c.Index);
即我正在寻找一种更有效或更优雅的方式来获得符合标准的物品位置。
您可以轻松添加自己的扩展方法:
public static IEnumerable<int> IndexesWhere<T>(this IEnumerable<T> source, Func<T, bool> predicate)
{
int index=0;
foreach (T element in source)
{
if (predicate(element))
{
yield return index;
}
index++;
}
}
然后将其与:
string[] s = {"zero", "one", "two", "three", "four", "five"};
var x = s.IndexesWhere(t => t.StartsWith("t"));
如果您只是将示例用作学习 LINQ 的一种方式,请忽略这篇文章。
我不清楚 LINQ 是否实际上是执行此操作的最佳方法。 下面的代码似乎更有效,因为不需要创建新的匿名类型。 当然,您的示例可能是人为的,并且该技术在不同的上下文中可能更有用,例如在可以利用值索引的数据结构中,但下面的代码相当直接,易于理解(无需思考),并且可以说更有效。
string[] s = {"zero", "one", "two", "three", "four", "five"};
List<int> matchingIndices = new List<int>();
for (int i = 0; i < s.Length; ++i)
{
if (s[i].StartWith("t"))
{
matchingIndices.Add(i);
}
}
似乎很好。您可以通过将选择更改为以下选项来保存几个字符:
.Select((Value, Index) => new {Value, Index})
集合列表中还有 FindIndex 方法,您可以为其创建一个 delete 方法,该方法可以从集合中返回索引。 您可以参考 MSDN http://msdn.microsoft.com/en-us/library/x1xzf2ca.aspx 中的以下链接。
这个怎么样? 它与原始海报的类似,但我首先选择索引,然后构建符合标准的集合。
var x = s.Select((a, i) => i).Where(i => s[i].StartsWith("t"));
这比其他一些答案效率低,因为该列表已完全迭代两次。
我和一位同事讨论了这个有趣的问题,起初我认为 JonSkeet 的解决方案很棒,但我的同事指出了一个问题,即如果函数是 IEnumerable<T>
的扩展,那么它可以在集合实现它的地方使用。
对于数组,可以肯定地说,使用 foreach
生成的订单将得到尊重(即 foreach
将从第一个迭代到最后一个),但其他集合(列表、字典等)不一定如此,其中foreach
不一定反映"条目顺序"。然而,功能就在那里,它可能具有误导性。
最后,我最终得到了类似于 tvanfosson 的答案,但作为数组的扩展方法:
public static int[] GetIndexes<T>(this T[]source, Func<T, bool> predicate)
{
List<int> matchingIndexes = new List<int>();
for (int i = 0; i < source.Length; ++i)
{
if (predicate(source[i]))
{
matchingIndexes.Add(i);
}
}
return matchingIndexes.ToArray();
}
希望List.ToArray
能尊重最后一次手术的命令......