如何在数组中查找值的索引,忽略指定值的索引

时间:2017-06-25 13:47:08

标签: c# .net vb.net linq

可以使用Linq来查找数组中值的索引,同时忽略特定值的索引吗?

EG。 array = {1,2,3,4,0,5,0,6,7}

指数6是7 如果我选择忽略全零的索引 而是返回5作为索引6 通过计数超过0但在数组中保持0。

4 个答案:

答案 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