有更好的方法吗?

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})

Collection List中还有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产生的顺序将被尊重(即List.ToArray将从头到尾迭代),但不一定是其他集合(List,Dictionary,等),其中<=>不会反映必然 <!> quot;条目的顺序<!>“;然而功能就在那里,它可能会产生误导。

最后,我最终得到了类似于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();
}

这里希望<=>会尊重最后一次操作的顺序......

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top