【问题标题】:Convert array to tuple?将数组转换为元组?
【发布时间】:2017-06-06 09:34:33
【问题描述】:

是否可以在 C# 中将数组转换为元组?像这样的:

var ar = new int[2] {5, 7};
Tuple<int,int> t = Tuple.Create(ar);

【问题讨论】:

  • 如果你知道数组的大小,你可以传递ar[0], ar[1]的值
  • 只有事先知道数组的大小才有意义。然后使用C#7 你可以这样做:(int a, int b) = (ar[0], ar[1]); (它的优点是你可以命名元组元素)。
  • 这里的主要问题是数组的大小(以及Tuple&lt;&gt;的大小)必须在编译时知道:在你写的代码中,你明确写了Tuple&lt;int, int&gt;。您可以轻松地创建一个方法,给定一个包含两个(或更多)元素的数组,返回 Tuple&lt;T, T&gt;

标签: c# arrays tuples


【解决方案1】:

不,System.Tuple 有一个最大大小是有充分理由的。对于您似乎正在做的工作,这只是错误的工具。为什么不只返回数组而不是元组?您的方法最终可能需要一个包含数十个元素的元组,这非常荒谬且根本无法维护。

最好不要返回数组,而是返回一个接口,例如ICollection&lt;T&gt;IEnumerable&lt;T&gt;

【讨论】:

  • not at all maintainable - 正是我想说的
  • 我认为提问者可能一直在考虑数组大小在编译时已知的情况。例如,一个较旧的 API 早于元组,它返回一个由四个字符串组成的数组。或者,如果您已经对已知数量的捕获字段进行了正则表达式匹配,现在想要将结果打包为一个元组。
【解决方案2】:

现在使用 C# 7.0,您可以创建扩展方法来将数组解构为 ValueTuple,这使得

var (p1,p2,p3) = s.Split(':');

可能。

public static class ArrayExt {
    public static void Deconstruct<T>(this T[] srcArray, out T a0) {
        if (srcArray == null || srcArray.Length < 1)
            throw new ArgumentException(nameof(srcArray));

        a0 = srcArray[0];
    }

    public static void Deconstruct<T>(this T[] srcArray, out T a0, out T a1) {
        if (srcArray == null || srcArray.Length < 2)
            throw new ArgumentException(nameof(srcArray));

        a0 = srcArray[0];
        a1 = srcArray[1];
    }

    public static void Deconstruct<T>(this T[] srcArray, out T a0, out T a1, out T a2) {
        if (srcArray == null || srcArray.Length < 3)
            throw new ArgumentException(nameof(srcArray));

        a0 = srcArray[0];
        a1 = srcArray[1];
        a2 = srcArray[2];
    }

    public static void Deconstruct<T>(this T[] srcArray, out T a0, out T a1, out T a2, out T a3) {
        if (srcArray == null || srcArray.Length < 4)
            throw new ArgumentException(nameof(srcArray));

        a0 = srcArray[0];
        a1 = srcArray[1];
        a2 = srcArray[2];
        a3 = srcArray[3];
    }

    public static void Deconstruct<T>(this T[] srcArray, out T a0, out T a1, out T a2, out T a3, out T a4) {
        if (srcArray == null || srcArray.Length < 5)
            throw new ArgumentException(nameof(srcArray));

        a0 = srcArray[0];
        a1 = srcArray[1];
        a2 = srcArray[2];
        a3 = srcArray[3];
        a4 = srcArray[4];
    }

    public static void Deconstruct<T>(this T[] srcArray, out T a0, out T a1, out T a2, out T a3, out T a4, out T a5) {
        if (srcArray == null || srcArray.Length < 6)
            throw new ArgumentException(nameof(srcArray));

        a0 = srcArray[0];
        a1 = srcArray[1];
        a2 = srcArray[2];
        a3 = srcArray[3];
        a4 = srcArray[4];
        a5 = srcArray[5];
    }

    public static void Deconstruct<T>(this T[] srcArray, out T a0, out T a1, out T a2, out T a3, out T a4, out T a5, out T a6) {
        if (srcArray == null || srcArray.Length < 7)
            throw new ArgumentException(nameof(srcArray));

        a0 = srcArray[0];
        a1 = srcArray[1];
        a2 = srcArray[2];
        a3 = srcArray[3];
        a4 = srcArray[4];
        a5 = srcArray[5];
        a6 = srcArray[6];
    }

    public static void Deconstruct<T>(this T[] srcArray, out T a0, out T a1, out T a2, out T a3, out T a4, out T a5, out T a6, out T a7) {
        if (srcArray == null || srcArray.Length < 8)
            throw new ArgumentException(nameof(srcArray));

        a0 = srcArray[0];
        a1 = srcArray[1];
        a2 = srcArray[2];
        a3 = srcArray[3];
        a4 = srcArray[4];
        a5 = srcArray[5];
        a6 = srcArray[6];
        a7 = srcArray[7];
    }
}

【讨论】:

    【解决方案3】:

    通过这样做,您可以获得元组列表,但我看不出这样做的原因:

          var ar = new int[2] { 5, 7 };
    
            List<Tuple<int>> result = ar
                .Select(x => Tuple.Create(x))
                .ToList();
    

    或者如果你想把它放在一个元组中:

       var ar = new int[2] { 5, 7 };
        Tuple<int[]> result = Tuple.Create(ar);
    

    如果您知道尺寸,请执行以下操作:

      Tuple<int, int> tuple = Tuple.Create(ar[0], ar[1]);
    

    【讨论】:

      【解决方案4】:

      那么我们为什么不这样做呢

      public static Tuple<T, T> CreateTuple<T>(T[] array, int totalItem = 2)
      {
          if (arr.length % totalItem != 0)
          throw new Exception("Error the length dose not consist with totalItem");
      
          return Tuple.Create(arr);
      }
      

      这里我们验证每个项目都有一个和两个。

      【讨论】:

      • 在某些非常好的情况下,您希望这样做,例如已知数组大小时。所以说总的来说这是一个坏主意有点苛刻。
      • 这可能会产生编译器错误:Error CS0029: Cannot implicitly convert type 'System.Tuple&lt;T[]&gt;' to 'System.Tuple&lt;T, T&gt;'
      【解决方案5】:

      你可以使用子元组,例如这个

      var tupArray = new Tuple<dynamic,dynamic,dynamic,dynamic,dynamic,dynamic,dynamic,Tuple<dynamic,dynamic>>
      (
          a[0],a[1],a[2],a[3],a[4],a[5],a[6],new Tuple<dynamic,dynamic>(a[7],a[8])
      )
      

      【讨论】:

        【解决方案6】:

        你的想法是个坏主意...数组和元组在 C#/.NET 中不会“混合”。有些语言的数组和类之间的距离很小(比如 Javascript,使用 [...] 运算符可以同时使用数组和对象)。 C# 不是这些语言之一。 Tuples 没有为此定义 this[int n] 索引器。

        但是你要代码,所以我给你代码。

        这里的主要问题是数组的大小(以及Tuple&lt;&gt; 的大小)必须在编译时知道:在您编写的代码中,您明确地编写了Tuple&lt;int, int&gt;。您可以轻松地创建一个方法,给定一个包含两个(或更多)元素的数组,返回 Tuple&lt;T, T&gt;,例如:

        public static Tuple<T, T> CreateTuple2<T>(T[] array)
        {
            if (array == null || array.Length < 2)
            {
                throw new ArgumentException(nameof(array));
            }
        
            return Tuple.Create(array[0], array[1]);
        }
        

        从这里你可以创建其他CreateTuple3()CreateTuple4()...

        【讨论】:

        • 这是一个糟糕的建议。
        • @user9993 我认为这是一个“答案”,而不是“建议”。 “问题”很糟糕(在 C#/.NET 中混合数组和元组是一个坏主意),但他要求一段代码(是否可以在 C# 中将数组转换为元组?像这样:),所以我把它给了他。
        • 从理论上讲,不需要知道 Tuple 的大小:您可以创建一个单独的方法,通过反射来动态构建 Tuple 根据数组的大小(假设它不超过元组的最大 N 参数)并将其返回为 objectdynamic 并邪恶地嘲笑它的用户未来的困境(哦,你有对象吗?所以只是投它 muahahaha)。或者创建一个以类似方式工作的TTuple CreateTuple&lt;TTuple&gt;(object[] vals),并以类似的方式邪恶地笑(只需调用它 CreateTuple..).. 或者,(... )
        • 但我想做var (p1,p2,p3) = str.Split(':');
        • 现在我想在 C# 中实现 Perl 的解包,并能够像 Perl 一样将它与元组赋值一起使用:var (s1,s2) = unpack("A4x2A4", test);
        猜你喜欢
        • 2012-04-18
        • 1970-01-01
        • 2015-12-02
        • 2014-09-04
        • 1970-01-01
        • 1970-01-01
        • 2012-10-09
        相关资源
        最近更新 更多