C# 数组和列表的基本知识及 LINQ 查询

数组和列表的基本知识及 LINQ 查询

  • 一、基本知识
  • 二、引用命名空间声明
  • 三、数组
  • [四、列表 List](#四、列表 List)
  • [五、数组和列表使用 LINQ的操作和运算](#五、数组和列表使用 LINQ的操作和运算)
    • [5.1、一维 LIST 删除所有含 double.NaN 的行](#5.1、一维 LIST 删除所有含 double.NaN 的行)
    • [5.2、一维 LIST 删除所有含指定数据的行](#5.2、一维 LIST 删除所有含指定数据的行)
    • [5.3、一维 LIST 获得非重复的数列](#5.3、一维 LIST 获得非重复的数列)
      • [5.3.1、使用 LINQ 的 Distinct 方法](#5.3.1、使用 LINQ 的 Distinct 方法)
      • [5.3.2、使用 HashSet 方法](#5.3.2、使用 HashSet 方法)
    • [5.4、二维 LIST 的声明、初始化和访问](#5.4、二维 LIST 的声明、初始化和访问)
    • [5.5、二维 LIST 使用 LINQ 筛选掉包含 double.NaN 的行及空行](#5.5、二维 LIST 使用 LINQ 筛选掉包含 double.NaN 的行及空行)
    • [5.6、二维 list<list<T>> 删除 某列值相同的行](#5.6、二维 list<list<T>> 删除 某列值相同的行)
      • [5.6.1、保留第一列数据相同的首行的 LIST](#5.6.1、保留第一列数据相同的首行的 LIST)
      • [5.6.2、保留第一列数据相同的最后一行的 LIST](#5.6.2、保留第一列数据相同的最后一行的 LIST)
      • [5.6.3、使用LINQ去重,保留第一列数据相同的首行的 LIST](#5.6.3、使用LINQ去重,保留第一列数据相同的首行的 LIST)
      • [5.6.4、使用LINQ去重,移除 LIST 第一列所有数据相同的行](#5.6.4、使用LINQ去重,移除 LIST 第一列所有数据相同的行)
  • [六、二维 LIST 和二维数组相互转换](#六、二维 LIST 和二维数组相互转换)
    • [6.1、二维数组 int[,] 与 交错数组 int[][] 的区别](#6.1、二维数组 int[,] 与 交错数组 int[][] 的区别)
    • [6.2、二维 LIST 转换为 交错数组](#6.2、二维 LIST 转换为 交错数组)
    • [6.3、二维 LIST 转换为二维数组](#6.3、二维 LIST 转换为二维数组)
    • [6.4、使用 LINQ,简洁地将二维数组 T[,] 转换为二维 List<List<T>>](#6.4、使用 LINQ,简洁地将二维数组 T[,] 转换为二维 List<List<T>>)
  • [七、字符串分割成 List<T>](#七、字符串分割成 List<T>)
      • [7.1、字符串分割成 List<字符串>](#7.1、字符串分割成 List<字符串>)
      • [7.2、字符串分割为 List<int> 或 T 为其他数值类型](#7.2、字符串分割为 List<int> 或 T 为其他数值类型)

一、基本知识

数组和列表是 C# 操作计算数据的基础,配合 LINQ 查询可以实现代码的简洁访问。

LINQ 语言集成查询(Language Integrated Query)是.NET框架的扩展,一系列直接将查询功能集成到 C# 语言的技术统称,是一种使用类似 SQL 语句操作多种数据源的功能。List 类是 ArrayList 类的泛型等效类。数组可以是多维数据。

二、引用命名空间声明

csharp 复制代码
using System;
using System.Linq;
using System.Collections.Generic;

三、数组

3.1、一维数组

csharp 复制代码
double[] OneDimensionalArray = { 1.0, 2.0, double.NaN };

3.2、二维数组

csharp 复制代码
double[,] TwoDimensionalArray = {
            { 1.0, 2.0, double.NaN },
            { 3.0, 4.0, 5.0 },
            { double.NaN, 6.0, 7.0 }
        }; 

3.3、不规则数组 Jagged Array

也叫交错数组。不同长度的行,可以使用 Jagged Array。使用Jagged Array时,每行的长度可以不同,这在某些情况下比使用List<List>更灵活。选择哪种方式取决于你的具体需求,比如是否需要动态改变行的长度。

csharp 复制代码
int[][] jaggedArray = new int[3][]; // 声明一个三行的数组,每行的长度可以根据需要进行定义和修改。
jaggedArray[0] = new int[] { 1, 2 }; // 第一行有两个元素
jaggedArray[1] = new int[] { 3, 4, 5 }; // 第二行有三个元素
jaggedArray[2] = new int[] { 6 }; // 第三行有一个元素

四、列表 List

4.1、一维列表

csharp 复制代码
List<double> OneDimensionalList = new List<double> { 1.8, 2.9, 3.7, 4.5 , double.NaN };
List<int> OneDimensionalList = new List<int> { 1, 2, 3, 4, 5 };
List<string> OneDimensionalList = new List<string> { "Alice", "Bob", "Charlie" };
List<object> OneDimensionalList = new List<object> { 1, "Hello", 3.14 };

4.2、二维列表

严格不叫二维,但可以等效数组一样操作,姑且这么称呼。

csharp 复制代码
List<List<int>> TwoDimensionalList = new List<List<int>>() {
          new List<int> { 1, 2, 3 },
          new List<int> { 4, 5, 6 },
          new List<int> { 7, 8, 9 },
};


List<List<int>> TwoDimensionalList = new List<List<int>>();
TwoDimensionalList.Add(new List<int> { 1, 2, 3 });// 添加行
TwoDimensionalList.Add(new List<int> { 4, 5, 6 });
TwoDimensionalList.Add(new List<int> { 7, 8, 9 });

五、数组和列表使用 LINQ的操作和运算

5.1、一维 LIST 删除所有含 double.NaN 的行

csharp 复制代码
List<double> OneDimensionalList = new List<double> { 1.8, 2.9, 3.7, 4.5 , double.NaN, 168 };
OneDimensionalList.RemoveAll(n => double.IsNaN(n));

5.2、一维 LIST 删除所有含指定数据的行

csharp 复制代码
List<string> OneDimensionalList = new List<string> { 
"Alice TWO Y", 
"Bob WO", 
"Charlie who Y"
"Hi LIST"
};
foreach (string row in OneDimensionalList)
{
    string[] SplitString = row.Split(' ');//行数据分裂
    if (SplitString[2] == "Y")//第3个字符等于Y的
    {
     OneDimensionalList.RemoveAll(x => x == row);//删除第3列等于字符Y的行
    }
}

// 在指定位置插入元素(例如,在索引为2的位置插入7)
 OneDimensionalList.Insert(2, 7);
 
// 移除指定值的第一个匹配项(如果有的话)
OneDimensionalList.Remove(7); // 如果7存在,则移除它
OneDimensionalList.RemoveAt(0); // 移除索引为0的元素,即原本的1
OneDimensionalList.Clear(); // 清空列表中的所有元素
bool containsThree = OneDimensionalList.Contains(3); //检查元素是否存在于列表中,如果3存在,返回true,否则返回false
int count =  OneDimensionalList.Count; // 获取列表中的元素数量

5.3、一维 LIST 获得非重复的数列

5.3.1、使用 LINQ 的 Distinct 方法

csharp 复制代码
List<string> OneDimensionalList = new List<string> { 
"Alice TWO Y", 
"Bob WO", 
"Charlie who Y"
"Hi LIST"
"Charlie who Y"
};
OneDimensionalList = OneDimensionalList.Distinct().ToList();//返回非重复的数列
OneDimensionalList.Sort();//排序

5.3.2、使用 HashSet 方法

csharp 复制代码
List<string> OneDimensionalList = new List<string> { 
"Alice TWO Y", 
"Bob WO", 
"Charlie who Y"
"Hi LIST"
"Charlie who Y"
};
HashSet<string> hs = new HashSet<string>(OneDimensionalList); //HashSet存储一组不重复的元素
OneDimensionalList = hs.ToList(); 
OneDimensionalList.Sort();//排序

5.4、二维 LIST 的声明、初始化和访问

csharp 复制代码
//声明新的二维列表
List<List<int>> twoDimensionalList = new List<List<int>>();

//初始化二维列表 List ,添加 3 行 4 列
twoDimensionalList.Add(new List<int> { 1, 2, 3, 4 });//添加一维 List 元素
twoDimensionalList.Add(new List<int> { 5, 6, 7, 8 });
twoDimensionalList.Add(new List<int> { 9, 10, 11, 12 });

// 获取二维列表行数
int rowCount = twoDimensionalList.Count;

// 获取二维列表列数
int columnCount = twoDimensionalList.Count == 0 ? 0 : twoDimensionalList[0].Count;
int cols = twoDimensionalList.Select(row => row.Count).Max(); // 假设所有行长度相同,如果不是,需要处理不一致的情况

//简单访问二维 List 元素或值
int element = twoDimensionalList[0][1]; // 获取第一行、第二列元素的值(行索引为 0,列索引为 1),值为 2
Console.WriteLine(element);
twoDimensionalList[1][2] = 5; // 将第二行第三列的元素修改为5


//遍历二维列表,控制台输出
foreach (List<int> row in twoDimensionalList)
{
   foreach (int item in row)
    {
        Console.Write(item + " ");//控制台调试显示数据
    }
     Console.WriteLine();
}

foreach (var row in twoDList)
{
    foreach (var item in row)
    {
        Console.Write(item + " ");
    }
    Console.WriteLine(); // 换行,用于分隔各行
}

//遍历二维列表,修改数据,控制台输出,
for (int i = 0; i < rowCount; i++)
{
    for (int j = 0; j < columnCount; j++)
    {
       twoDimensionalList[i][j] += 1;//修改数据,二维数据每个数加 1
    }
}

//二维数组或 LIST 控制台显示,采用 Join 输出行数据
foreach (var row in TwoDimensionalArray)
{
  Console.WriteLine(string.Join(", ", row));
}

foreach (var row in TwoDimensionalList)
{
  Console.WriteLine(string.Join(", ", row));
}

//删除列表行,索引默认从零开始
twoDimensionalList.RemoveAt(2);//删除索引 2 的行数据

//删除集合中一定范围内的元素,索引默认从零开始
twoDimensionalList.RemoveRange(0, 2);//从索引 0 开始,删除 2 行数据

//在列表索引前插入元素(在第二行之前插入)
twoDimensionalList.Insert(1, new List<int> { 15, 16, 17, 18 });

//在特定位置插入新行,初始化为 0(在第一行之前插入)
twoDList.Insert(0, new List<int>(Enumerable.Repeat(0, cols)));

//初始化一个具有特定大小和内容的二维List
int rows = 3;
int cols = 4;
List<List<int>> twoDList = new List<List<int>>();
for (int i = 0; i < rows; i++)
{
    twoDList.Add(new List<int>(Enumerable.Repeat(0, cols))); // 添加一个新行,初始化为0
}

5.5、二维 LIST 使用 LINQ 筛选掉包含 double.NaN 的行及空行

csharp 复制代码
 
 List<List<double>> TwoDimensionalList = new List<List<double>>()
 {
      new List<double> {  1.8, 2.9, 3.7, 4.5, 9.9, 168 },
      new List<double> {  1.8, 2.9, 3.7, 4.5, double.NaN, 168 },
      new List<double> { }, // 空行
      new List<double> {  2.8, 3.9, 4.7, 5.5, double.NaN, 668, },
      new List<double> {  1.8, 2.9, 3.7, 4.5, 9.9, 168 }
 };

 TwoDimensionalList = TwoDimensionalList.Where(row => !row.Contains(double.NaN) && row.Any()).ToList();//删除存在 double.NaN 的行及空行

// TwoDimensionalList = TwoDimensionalList.Where(row => row.Any()).ToList();//删除空行
// TwoDimensionalList = TwoDimensionalList.Where(row => !row.Contains(double.NaN)).ToList();//删除存在 double.NaN 的行

foreach (var row in TwoDimensionalList) { Console.WriteLine(string.Join(" ", row)); }

 //var filteredData = twoDimensionalList.Where(row => !row.Contains(double.NaN)).ToArray();

5.6、二维 list<list> 删除 某列值相同的行

5.6.1、保留第一列数据相同的首行的 LIST

csharp 复制代码
         List<List<int>> list1 = new List<List<int>>
        {
            new List<int> { 1, 2 }, //第一列数据相同的行
            new List<int> { 3, 4 },
            new List<int> { 1, 5 }, //第一列数据相同的行
            new List<int> { 6, 7 },
            new List<int> { 1, 6 }  //第一列数据相同的行
        };

            // 检查第一列(索引为0)
            int columnIndex = 0;
            var seen = new HashSet<int>(); // 用于跟踪已经看到的值
            for (int i = 0; i < list1.Count; i++) // 从 0 索引开始遍历行
            {
                if (!seen.Add(list1[i][columnIndex])) // 如果值已存在,则删除当前行
                {
                    list1.RemoveAt(i); // 如果值已存在,则删除当前行
                }
            }

            foreach (var row in list1)
            {
                Console.WriteLine(string.Join(", ", row));
            }
            Console.WriteLine();

结果:

1, 2

3, 4

6, 7

5.6.2、保留第一列数据相同的最后一行的 LIST

csharp 复制代码
            List<List<int>> list2 = new List<List<int>>
        {
            new List<int> { 1, 2 }, //第一列数据相同的行
            new List<int> { 3, 4 },
            new List<int> { 1, 5 }, //第一列数据相同的行
            new List<int> { 6, 7 },
            new List<int> { 1, 6 }  //第一列数据相同的行
        };

            int columnIndex = 0;// 检查第一列(索引为0)
            var uniqueValues = new HashSet<int>();
            for (int i = list2.Count - 1; i >= 0; i--) // 从后往前遍历以便安全删除元素
            {
                if (!uniqueValues.Add(list2[i][columnIndex]))
                {
                    list2.RemoveAt(i); // 如果值已存在,则删除当前行
                }
            }

            foreach (var row in list2)
            {
                Console.WriteLine(string.Join(", ", row));
            }
            Console.WriteLine(); 

结果:

3, 4

6, 7

1, 6

5.6.3、使用LINQ去重,保留第一列数据相同的首行的 LIST

csharp 复制代码
        List<List<int>> list3 = new List<List<int>>
        {
            new List<int> { 1, 2 }, //第一列数据相同的行
            new List<int> { 3, 4 },
            new List<int> { 1, 5 }, //第一列数据相同的行
            new List<int> { 6, 7 },
            new List<int> { 1, 6 }  //第一列数据相同的行
        };
        
        int columnIndex = 0;// 检查第一列(索引为0)
        list3 = list3.GroupBy(x => x[columnIndex]).Select(g => g.First()).ToList(); // 去重并保留第一个遇到的元素。
        foreach (var row in list3)
        {
           Console.WriteLine(string.Join(", ", row)); // 输出结果。
        }

结果:

1, 2

3, 4

6, 7

csharp 复制代码
        List<List<int>> list = new List<List<int>>()
        {
            new List<int> { 1, 2 }, //第一列数据相同的行
            new List<int> { 3, 4 },
            new List<int> { 1, 5 }, //第一列数据相同的行
            new List<int> { 6, 7 },
            new List<int> { 1, 6 },  //第一列数据相同的行
            new List<int> { 1, 2, 3 },//第一列数据相同的行
            new List<int> { 4, 5, 6 },
            new List<int> { 1, 7, 8 }, //第一列数据相同的行
            new List<int> { 9, 10, 11 }
        };

            int columnIndex = 0;// 检查第一列(索引为0)
            // 只保留每组中的第一个元素(如果有重复值的话)
            list = list.Where((item, index) => index == list.FindIndex(x => x[columnIndex] == item[columnIndex])) 
                                       .ToList();

            // 打印结果以验证
            foreach (var sublist in list)
            {
                Console.WriteLine(string.Join(", ", sublist));
            }
            return;

结果:

1, 2

3, 4

6, 7

4, 5, 6

9, 10, 11

5.6.4、使用LINQ去重,移除 LIST 第一列所有数据相同的行

csharp 复制代码
            List<List<int>> listOfLists = new List<List<int>>()
        {
            new List<int> { 1, 2, 3 },
            new List<int> { 4, 5, 6 },
            new List<int> { 1, 7, 8 }, // 这里有两行包含1
            new List<int> { 9, 10, 11 }
        };

            // 需要检查的列索引(例如第0列)
            int columnIndex = 0;

            // 获取该列的所有值及其出现的次数
            var duplicates = listOfLists.GroupBy(list => list[columnIndex])
                                        .Where(group => group.Count() > 1)
                                        .Select(group => group.Key)
                                        .ToList();

            // 移除所有包含重复值的行
            listOfLists.RemoveAll(list => duplicates.Contains(list[columnIndex]));

            // 打印结果以验证
            foreach (var list in listOfLists)
            {
                Console.WriteLine(string.Join(", ", list));
            }

结果:

4, 5, 6

9, 10, 11

六、二维 LIST 和二维数组相互转换

6.1、二维数组 int[,] 与 交错数组 int[][] 的区别

二维 LIST 转换为二维数组 double[][] arrayOfArrays,严格说不是二维数组。

关于 double[][] 是交错数组,它其实是一个 double[] 里嵌套着double[],可以理解为 (double[])[]。

对于int[,],数组的行数和列数如下:

csharp 复制代码
int[,] a=new int[2,3];
int row = a.GetLength(0);  //第一维的长度(即行数)  row=2;
int col = a.GetLength(1); //第二维的长度(即列数)col=3;
int length = a.Length;//二维数组的总长度  lenth=6;

对于交错数组 int[][]

csharp 复制代码
int[][] a = { new int[] { 1, 5 }, new int[] { 7, 3 }, new int[] { 3, 5 } };
   //accounts.Length表示数组a中一维数组的个数3
   for (int i = 0; i < accounts.Length; i++)
   {
     int col = accounts[i].Length;//表示一维数组中其中一维数组的个数,看上面数组a,那么这里数组的个数就为2
     int sum = 0;
      for (int j = 0; j < col; j++)
       {
         sum = sum + accounts[i][j];
       }         
    }

6.2、二维 LIST 转换为 交错数组

csharp 复制代码
List<List<double>> TwoDimensionalList = new List<List<double>>
{
    new List<double> { 1, 2, 3 },
    new List<double> { 4, 5, 6 },
    new List<double> { 7, 8, 9 }
};
//此二维数组不是double[,] arrayOfArrays 数组       
double[][] arrayOfArrays = TwoDimensionalList.Select(row => row.ToArray()).ToArray();

6.3、二维 LIST 转换为二维数组

6.3.1、直接转换

csharp 复制代码
List<List<string>> lists = new List<List<string>>()
{
  new List<string>() { "C", "C++" },
  new List<string>() { "Java", "Kotlin" }
};

string[,] arrays = new string[lists.Count, lists[0].Count];
for (int i = 0; i < lists.Count; i++)
{
     for (int j = 0; j < lists[i].Count; j++)
     {
         arrays[i, j] = lists[i][j];
     }
}

//控制台输出二维数组结果
foreach (var array in arrays)
{
      Console.WriteLine(String.Join(", ", array));
}

//控制台输出结果(取数组的行列大小)
for (int i = 0; i < arrays.GetLength(0); i++)
{
     for (int j = 0; j < arrays.GetLength(1); j++)
     {
          Console.Write(arrays[i, j] + " ");
     }
     Console.WriteLine();
}

//控制台输出结果(取lists的行列大小)
int rows = lists.Count;
int cols = lists[0].Count;
for (int i = 0; i < rows; i++)
{
     for (int j = 0; j < cols; j++)
     {
         Console.Write(arrays[i, j] + " ");
     }
     Console.WriteLine();
}

6.3.2、使用交错数组作为转换过程

csharp 复制代码
List<List<double>> TwoDimensionalList = new List<List<double>>
{
new List<double> { 1, 2, 3 },
new List<double> { 4, 5, 6 },
new List<double> { 7, 8, 9 }
};
//先转换为行列规则的交错数组形式 double[][] arrayOfArrays
double[][] arrayOfArrays = TwoDimensionalList.Select(row => row.ToArray()).ToArray();

int rows = arrayOfArrays.Length;//交错数组行数
int cols = arrayOfArrays.Max(array => array.Length);//交错数组列数
double[,] multiDimArray=new double[rows, cols];//声明二维数组
//转换为二维数组
for (int i = 0; i < rows; i++)
{
     for (int j = 0; j < cols; j++)
     {
          multiDimArray[i, j] = arrayOfArrays[i][j]; // 直接赋值
     }
}
//控制台输出结果
for (int i = 0; i < multiDimArray.GetLength(0); i++)
{
     for (int j = 0; j < multiDimArray.GetLength(1); j++)
     {
          Console.Write(multiDimArray[i, j] + " ");
     }
     Console.WriteLine();
}

6.3.3、使用 List<数组>作为转换过程

方法1

csharp 复制代码
 List<List<int>> TwoDimensionalList = new List<List<int>>() {
          new List<int> { 1, 2, 3 },
          new List<int> { 4, 5, 6 },
          new List<int> { 7, 8, 9 }
            };
// 将List<List<int>>转换为List<int[]>
var listOfArrays = TwoDimensionalList.Select(row => row.ToArray()).ToList();

int[,] array = new int[listOfArrays.Count, listOfArrays[0].Length];
for (int i = 0; i < listOfArrays.Count; i++)
{
     for (int j = 0; j < listOfArrays[i].Length; j++)
     {
         array[i, j] = listOfArrays[i][j];
     }
}

// 输出结果验证
for (int i = 0; i < array.GetLength(0); i++)
{
     for (int j = 0; j < array.GetLength(1); j++)
     {
         Console.Write(array[i, j] + " ");
     }
     Console.WriteLine();
}

方法2

csharp 复制代码
        // 示例二维List
        List<List<int>> listOfLists = new List<List<int>>
        {
            new List<int> { 1, 2, 3 },
            new List<int> { 4, 5, 6 },
            new List<int> { 7, 8, 9 }
        };
 
        // 将List<List<int>>转换为List<int[]>
        List<int[]> listOfArrays = new List<int[]>();
        foreach (var list in listOfLists)
        {
            listOfArrays.Add(list.ToArray());
        }
 
 
        // 然后将List<int[]>转换为二维数组int[,]
        int[,] array = new int[listOfArrays.Count, listOfArrays[0].Length];
        for (int i = 0; i < listOfArrays.Count; i++)
        {
            for (int j = 0; j < listOfArrays[i].Length; j++)
            {
                array[i, j] = listOfArrays[i][j];
            }
        }
 
        // 输出结果验证
        for (int i = 0; i < array.GetLength(0); i++)
        {
            for (int j = 0; j < array.GetLength(1); j++)
            {
                Console.Write(array[i, j] + " ");
            }
            Console.WriteLine();
        }

6.4、使用 LINQ,简洁地将二维数组 T[,] 转换为二维 List<List>

csharp 复制代码
int[,] TwoDimensionalArray = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } };
int rowCount = TwoDimensionalArray.GetLength(0);
int colCount = TwoDimensionalArray.GetLength(1);

List<List<int>> TwoDimensionalList = Enumerable.Range(0, rowCount)
                    .Select(i => Enumerable.Range(0, colCount)
                    .Select(j => TwoDimensionalArray[i, j])
                    .ToList())
                    .ToList();

七、字符串分割成 List

7.1、字符串分割成 List<字符串>

csharp 复制代码
string input = "apple,banana,cherry";
List<string> result = new List<string>(input.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries));

7.2、字符串分割为 List 或 T 为其他数值类型

csharp 复制代码
string input = "1,2,3,4,5";
List<int> result = input.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
                                .Select(int.Parse)
                                .ToList();
 
foreach (var item in result)
{
    Console.WriteLine(item);
}
相关推荐
32码奴4 小时前
C#基础知识
开发语言·c#
来恩100313 小时前
C# 类与对象详解
开发语言·c#
Dr.勿忘16 小时前
C#面试常考随笔8:using关键字有哪些用法?
开发语言·unity·面试·c#·游戏引擎
xcLeigh16 小时前
WPF进阶 | WPF 数据绑定进阶:绑定模式、转换器与验证
c#·wpf
谢大旭17 小时前
ASP.NET Core 中间件
后端·中间件·c#
圣心17 小时前
Kafka 使用说明(kafka官方文档中文)
分布式·kafka·linq
时光追逐者17 小时前
Visual Studio使用GitHub Copilot提高.NET开发工作效率
c#·github·.net·copilot·ai编程·微软技术·visual studio
唐青枫19 小时前
dotnet LINQ 使用简明教程
c#·.net
谢大旭20 小时前
.Net Web API 访问权限限定
开发语言·c#