【问题标题】:Subset of Array in C#C#中数组的子集
【发布时间】:2010-12-20 00:46:45
【问题描述】:

如果我有一个包含 12 个元素的数组,并且我想要一个删除第一个和第 12 个元素的新数组。例如,如果我的数组如下所示:

__ __ __ __ __ __ __ __ __ __ __ __
a  b  c  d  e  f  g  h  i  j  k  l
__ __ __ __ __ __ __ __ __ __ __ __

我想对其进行转换或创建一个看起来像

的新数组
__ __ __ __ __ __ __ __ __ __

b  c  d  e  f  g  h  i  j  k 
__ __ __ __ __ __ __ __ __ __

我知道我可以通过迭代它们来做到这一点。我只是想知道 C# 中是否有更简洁的方法。

**已更新以修复错字。将 10 个元素更改为 12 个元素。

【问题讨论】:

  • “j”不是数组中的第 10 个元素吗?还是您的意思是第一个和最后一个元素?

标签: c# arrays


【解决方案1】:

LINQ 是你的朋友。 :)

var newArray = oldArray.Skip(1).Take(oldArray.Length - 2).ToArray();

当然比手动创建数组并对其进行迭代效率要低一些,但要简单得多...

使用Array.Copy的稍微冗长的方法如下。

var newArray = new int[oldArray.Count - 2];
Array.Copy(oldArray, 1, newArray, 0, newArray.Length);

【讨论】:

  • 我真的很喜欢你原来的答案。 LINQ 一直是我的朋友。我从来没有使用过skip and take。谢谢。
  • @L. Moser:没问题——也改回来了。 :) 是的,我想我每周都会发现一种新的有用的 LINQ 方法。
  • 如果您在Take 之后执行Skip,这不是更简单吗?喜欢:oldArray.Take(oldArray.Length - 1).Skip(1).ToArray()?无论哪种方式在效率上都可能相同。
  • 不是一个好的 LINQ 应用程序。如果您已经处于 char 数组级别,那就做对了。
  • @rolls,固定,ta!
【解决方案2】:

Linq 既漂亮又时髦,但如果您正在寻找 1-liner,您可以将自己的实用程序函数组合在一起:

static class ArrayUtilities
{
    // create a subset from a range of indices
    public static T[] RangeSubset<T>(this T[] array, int startIndex, int length)
    {
        T[] subset = new T[length];
        Array.Copy(array, startIndex, subset, 0, length);
        return subset;
    }

    // create a subset from a specific list of indices
    public static T[] Subset<T>(this T[] array, params int[] indices)
    {
        T[] subset = new T[indices.Length];
        for (int i = 0; i < indices.Length; i++)
        {
            subset[i] = array[indices[i]];
        }
        return subset;
    }
}

那么您可以执行以下操作:

        char[] original = new char[] { 'a', 'b', 'c', 'd', 'e', 'f', 'g' };

        // array containing 'b' - 'f'
        char[] rangeSubset = original.RangeSubset(1, original.Length - 2);

        // array containing 'c', 'd', and 'f'
        char[] specificSubset = original.Subset(2, 3, 5);

【讨论】:

    【解决方案3】:

    C# 8 有一个RangeIndex 类型

    char[] a = { 'a', 'b', 'c',  'd',  'e',  'f',  'g',  'h',  'i',  'j',  'k',  'l' };
    Index i1 = 1;  // number 1 from beginning
    Index i2 = ^1; // number 1 from end
    var slice = a[i1..i2]; // { 'b','c','d','e','f','g','h','i','j' }
    

    【讨论】:

      【解决方案4】:

      您可以使用ArraySegment&lt;T&gt; 结构,如下所示:

      var arr = new[] { 1, 2, 3, 4, 5 };
      var offset = 1;
      var count = 2;
      var subset = new ArraySegment<int>(arr, offset, count)
                   .ToArray(); // output: { 2, 3 }
      

      在此处查看extension method,它可以更轻松地使用它。

      【讨论】:

        【解决方案5】:

        您可以使用 Array.Copy 或 LINQ 完成此操作。

        var letters = string[] { "a", "b", "c", "d", "e", "f", "g", "h", "i" };
        
        int length = letters.Length - 2;
        var items = new string[length];
        Array.Copy(letters, 1, items, 0, length);
        // or
        var items = letters.Skip(1).Take(length).ToArray();
        

        【讨论】:

          【解决方案6】:

          Array.Copy() 会为您执行此操作,但您仍然必须创建具有正确大小的新数组。

          【讨论】:

            【解决方案7】:
            string[] s = initialize the array...
            
            var subset = s.Skip(1).Take(s.Length - 2).ToArray();
            

            【讨论】:

              【解决方案8】:

              如果你想避免手动索引数组。不要尝试在任何地方拉请求:

              var newArray = oldArray.Skip(1).Reverse().Skip(1).Reverse().ToArray()
              

              【讨论】:

              • 这似乎没有删除最后一个元素。
              猜你喜欢
              • 2010-11-04
              • 2010-10-05
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2016-09-17
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多