代码之家  ›  专栏  ›  技术社区  ›  Neil Meyer

是否有一种方法可以对数组中除一个成员以外的所有成员执行操作?

c#
  •  2
  • Neil Meyer  · 技术社区  · 7 年前

    我一直在努力解决日常编码问题,终于找到了这个问题。

    在新数组的索引i处,是数组中所有数字的乘积 除i处的数组外的原始数组。

    将是[120,60,40,30,24]。如果我们的输入是[3,2,1],那么 跟进:如果你不能使用除法怎么办?

    所以简单的方法是将数组中的所有元素相乘,然后除以[i],但问题是如果 I = 0 例外 错误

    我知道 函数,该函数对数组的所有成员执行操作,但是否有方法 改性骨料 这样它就可以 除一名成员外的所有成员 ,或者是否有其他函数/方法提供此功能?

    2 回复  |  直到 6 年前
        1
  •  5
  •   Dmitrii Bychenko    7 年前

    如果 source Where ,例如。

      int[] source = new int[] { 1, 2, 3, 4, 5 };
    
      int[] result = Enumerable
        .Range(0, source.Length)
        .Select(i => source
           .Where((value, index) => index != i) // all items except i-th
           .Aggregate((s, a) => s * a))         // should be multiplied 
        .ToArray();
    
      Console.Write(string.Join(", ", result));
    

    结果:

      120, 60, 40, 30, 24
    

    然而,解决方案已经过时 O(N**2) 时间复杂性;以防首字母 大的 O(N) 代码(是的,我们应该介意 ):

      int[] source = ...
    
      int[] result;
    
      int zeroCount = source.Count(item => item == 0);
    
      if (zeroCount >= 2)      // All zeroes case
        result = new int[source.Length];   
      else if (zeroCount == 1) // All zeroes save one value case
        result = source
          .Select(v => v == 0
             ? source.Where(item => item != 0).Aggregate((s, a) => s * a)
             : 0)
          .ToArray(); 
      else {                   // No zeroes case
        // long, 1L: to prevent integer overflow, e.g. for {1000000, 1000000} input
        long total = source.Aggregate(1L, (s, a) => s * a);
    
        result = source
          .Select(v => (int)(total / v)) // yes, it's a division...
          .ToArray(); 
      }
    
        2
  •  3
  •   D Stanley    7 年前

    除了一个指定的成员(您是按值还是按索引指定它)之外,没有在所有成员上聚合的内置函数

    然而,循环将非常简单,Linq为您提供 Where 方法,您可以在其中创建 你想要什么都行 然后可以将聚合应用于 后果

    array.Where((x,i) => i != 2).Sum();  // use 2 since the index is 0-based
    

    也没有一个内置的Linq方法 Product ,但我肯定有一个,或者你可以很容易地推出自己的。