可以使用Linq来查找数组中值的索引,同时忽略特定值的索引吗?
EG。 array = {1,2,3,4,0,5,0,6,7}
指数6是7 如果我选择忽略全零的索引 而是返回5作为索引6 通过计数超过0但在数组中保持0。
答案 0 :(得分:1)
FastReplaceFirstMatch
可能是您特定问题的最快选择(在对其中一个回复的评论中提到)。
我已经将一些基于LINQ的解决方案(比其他基于ToList
的解决方案要快得多)包含在您指定的问题中(在您的问题中,而不是评论澄清)。
using System;
using System.Collections.Generic;
using System.Linq;
namespace Test
{
public static class GenericExtensions
{
public static int IndexExcludingValue<T>(this IEnumerable<T> test, T valueToFind, T valueToExclude) where T : struct
{
return test.Where(z => !Equals(z, valueToExclude))
.Select((value, index) => new { value, index })
.FirstOrDefault(z => Equals(z.value, valueToFind))?.index ?? -1;
}
public static T[] FastReplaceFirstMatch<T>(this T[] test, T valueToFind, T valueToReplace) where T : struct
{
var hasBeenReplaced = false;
var index = Array.FindIndex(test, z => Equals(z, valueToFind));
if (index != -1)
{
test[index] = valueToReplace;
}
return test;
}
public static IEnumerable<T> ReplaceFirstMatch<T>(this IEnumerable<T> test, T valueToFind, T valueToReplace) where T : struct
{
var hasBeenReplaced = false;
return test
.Select(value =>
{
if (!hasBeenReplaced && Equals(value, valueToFind))
{
hasBeenReplaced = true;
value = valueToReplace;
}
return value;
});
}
}
public class Program
{
private static int[] bob = { 1, 2, 3, 4, 0, 5, 0, 6, 7 };
static void Main(string[] args)
{
Console.WriteLine(bob.IndexExcludingValue(6, 0));
Console.WriteLine(string.Join(",", bob.ReplaceFirstMatch(6, 8).ToArray()));
Console.WriteLine(string.Join(",", bob.FastReplaceFirstMatch(6, 10)));
Console.ReadLine();
}
}
}
答案 1 :(得分:1)
如,
var x = new[] { 0, 1, 3, 0, 4, 5, 6 };
使用ToList()
x.Where(i => i != 0).ToList().IndexOf(5);
使用ToArray()
Array.FindIndex(x.Where(i => i != 0).ToArray(), i => i == 5);
答案 2 :(得分:0)
此刻我能想到的就是用它来忽略数组中的特定元素:
array.Where(e => e != 0);
然后这就得到索引:
array.Where(e => e != 0).ToList().IndexOf(6);
答案 3 :(得分:0)
在我看来更容易添加另一个解决方案:您可以再次消除零,将生成的可枚举转换为列表,然后在此列表中使用IndexOf
:
array.Where(x => x != 0)
.ToList().IndexOf(6); //Results in 5 as well
另外,在我看来,更漂亮的解决方案,您可以编写这样的扩展方法:
public static class Extensions
{
public static int IndexOfIgnoring<T> (this IEnumerable<T> collection, T indexOf, T toIgnore) =>
collection.Where (arg => !Equals (arg, toIgnore)).ToList ().IndexOf (indexOf);
}
你可以这样使用:
static void Main (string [] args)
{
Console.WriteLine ($"{new [] {1, 2, 3, 4, 0, 5, 0, 6, 7}.IndexOfIgnoring (6, 0)}");
Console.ReadLine ();
}
您可以阅读有关扩展方法here的更多信息。
编辑正如OP的评论问我,这是一个解决方案,在索引处设置项目,忽略特定项目。
因此我想再次使用扩展方法:
public static class Extensions
{
public static int IndexOfIgnoring<T> (this IEnumerable<T> collection, T indexOf, T toIgnore) =>
collection.Where (arg => !Equals (arg, toIgnore)).ToList ().IndexOf (indexOf);
public static int GetRealIndexOfIgnoring<T> (this IEnumerable<T> collection, int indexIgnored, T toIgnore)
=> collection.Select ((t, i) => new Tuple<T, int> (t, i)).Where (arg => !Equals (arg.Item1, toIgnore)).
ToList () [indexIgnored].Item2;
public static IEnumerable<T> SetAtIndexOfIgnoring<T> (this IEnumerable<T> collection, int indexIgnored, T toIgnore, T toSet)
{
var enumerable = collection as IList<T> ?? collection.ToList ();
return enumerable.Select ((t, i) => i == GetRealIndexOfIgnoring (enumerable, indexIgnored, toIgnore) ? toSet : t);
}
}
我们可以这样使用:
static void Main (string [] args)
{
var collection = new [] {1, 2, 3, 4, 0, 5, 0, 6, 7};
var ignoredIndex = collection.IndexOfIgnoring (6, 0);
Console.WriteLine ($"{ignoredIndex}");
collection = collection.SetAtIndexOfIgnoring(ignoredIndex, 0, 10).ToArray();
Console.WriteLine(string.Join(", ", collection));
Console.ReadLine ();
}
哪个输出:
5
1, 2, 3, 4, 0, 5, 0, 10, 7