【问题标题】:C# function for creating jagged array用于创建交错数组的 C# 函数
【发布时间】:2021-08-02 18:58:27
【问题描述】:

我有一个问题,我想创建一个锯齿状数组。但是这个锯齿状数组的大小是可变的。 这是否与像这样填充普通数组的方式相同?

int[] terms = new int[400];
for (int runs = 0; runs < 400; runs++)
{
    terms[runs] = value;
}

我使用的值是这样定义的:

public static string[] nodeCassette0 = { "03", "08" };
public static string[] nodeCassette1 = { "04", "09" };
public static string[] nodeCassette2 = { "05", "10" };
public static string[] nodeCassette3 = { "06", "11" };
public static string[] nodeCassette4 = { "07", "12" };

根据用户所需的大小,需要根据所需的大小填充新的变量 nodeCassette。数组的填充顺序始终相同,从 0 开始,到 4 结束。

应该是这样的,但我不知道如何动态创建它:

public string[][] nodeCassette =
{ 
    nodeCassette0,
    nodeCassette1,
    nodeCassette2,
    nodeCassette3,
    nodeCassette4
};

【问题讨论】:

  • 你应该使用List&lt;int&gt;而不是int[]然后你不需要指定大小
  • 这是一个简单的解决方法,但我如何创建函数来填充此列表?
  • 是的,它的工作方式与填充普通数组相同。
  • var terms = new List&lt;int&gt;(); 和你的循环内terms.Add(value)
  • @OlivierRogier 我正在从 Windows 表单中读取值,因此第一部分几乎是正确的。但是,据我所知,您评论中的其余部分是完全正确的

标签: c# arrays for-loop jagged-arrays


【解决方案1】:

这是一个如何创建这样一个锯齿状数组的示例:

int[] sizes = new int[] { 3, 2, 1, 1, 3 };

int[][] jagged = new int[sizes.Length][];

for (int i = 0; i < sizes.Length; i++)
{
    jagged[i] = new int[sizes[i]];
    for (int j = 0; j < sizes[i]; j++)
    {
        jagged[i][j] = (i + 1) * (j + 1);
    }
}

产生:


字符串也不例外:

int[] sizes = new int[] { 3, 2, 1, 1, 3 };

string[][] jagged = new string[sizes.Length][];

for (int i = 0; i < sizes.Length; i++)
{
    jagged[i] = new string[sizes[i]];
    for (int j = 0; j < sizes[i]; j++)
    {
        jagged[i][j] = $"{i}_{j}";
    }
}

【讨论】:

  • 我了解它如何与 int 一起使用,但它如何与字符串数据一起使用?
  • @Zjwamerjong - 字符串没有什么不同。我已经更新了答案。
【解决方案2】:

我们可以使用反射和Linq。

using System.Reflection;
using System.Linq;

默认使用这个专用类来存储数组,以及初始化可能元素的完整列表,并提供获取切片的方法,即由前 n 个元素组成的列表:

static class DefaultArrays
{
  static public string[] NodeCassette0 = { "03", "08" };
  static public string[] NodeCassette1 = { "04", "09" };
  static public string[] NodeCassette2 = { "05", "10" };
  static public string[] NodeCassette3 = { "06", "11" };
  static public string[] NodeCassette4 = { "07", "12" };

  static public List<string[]> All { get; private set; }

  static public List<string[]> Take(int count)
  {
    return All.Take(count).ToList();
  }

  static public void Initialize()
  {
    All = typeof(DefaultArrays).GetFields()
                               .Where(field => field.FieldType == typeof(string[]))
                               .OrderBy(field => field.Name.Length)
                               .ThenBy(field => field.Name)
                               .Select(field => (string[])field.GetValue(null))
                               .ToList();
  }

  static DefaultArrays()
  {
    Initialize();
  }
}

Initialize 方法以这种方式创建,以便在数组在运行时被修改的情况下允许更新整个列表,否则代码可以直接放在构造函数中,并且所有数组都标记为readonly

这是All的算法:

  • 我们通过类型名称获取静态类的所有字段。
  • 我们过滤以仅选择字符串数组类型的那些。
  • 我们按字段名称字符串长度排序。
  • 然后通过这个名称,因此我们最终从 40、30、2、1 得到例如 1、2、30、40。
  • 我们进行投影以获取值的引用而不是使用它的字段名称。
  • 我们将 Linq 查询转换为 List&lt;string&gt; 对象实例以返回。

假设所有数组都已命名,它使用伪自然数字排序:

"[same_same][number_without_trailing_left_0]"

否则我们可以使用自定义比较器:

How do I sort strings alphabetically while accounting for value when a string is numeric?

sort string-numbers

测试

var slice = DefaultArrays.Take(3);

string msg = string.Join(Environment.NewLine, slice.Select(item => string.Join(", ", item)));

Console.WriteLine(msg);

输出

03, 08
04, 09
05, 10

警告

切片包含对原始数组的引用列表,因此对该列表中数组单元格的任何修改都将反映在静态类中的匹配数组中。

否则我们需要使用Array.Copy 复制数组,而不是使用Linq.Take

  static public List<string[]> TakeCopy(int count)
  {
    var list = new List<string[]>();
    foreach ( int index in Enumerable.Range(0, Math.Min(count, All.Count)))
    {
      int length = All[index].Length;
      var array = new string[length];
      Array.Copy(All[index], array, length);
      list.Add(array);
    }
    return list;
  }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-10
    • 2015-03-04
    • 2011-02-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多