在C#中是否可以使用二维列表?


89

我想建立一个多维列表。作为参考,我正在研究一个播放列表分析器。

我有一个文件/文件列表,程序将其保存在标准列表中。每个列表条目中文件的一行。

然后,我使用正则表达式分析列表以查找特定行。行中的某些数据/结果需要放入新的多维列表中;由于我不知道会得到多少结果/数据,因此无法使用多维数组。

这是我要插入的数据:

清单
(
    [0] =>列表
        (
            [0] =>曲目ID
            [1] =>名称
            [2] =>艺术家
            [3] =>相册
            [4] =>播放次数
            [5] =>跳过计数

        )
    [1] =>列表
        (
等等....

真实的例子:

清单
(
    [0] =>列表
        (
            [0] => 2349
            [1] =>人生的黄金时间
            [2] =>傻朋克
            [3] =>毕竟人类
            [4] => 3
            [5] => 2

        )
    [1] =>列表
        (

所以,是的,mlist [0] [0]将从歌曲1中获取TrackID,mlist [1] [0]从歌曲2中获取,依此类推。

但是我在创建多维列表时遇到了很大的问题。到目前为止,我已经提出了

List<List<string>> matrix = new List<List<string>>();

但是我真的没有什么进步:(

Answers:


137

好吧,您当然可以List<List<string>>其中写一个:

List<string> track = new List<string>();
track.Add("2349");
track.Add("The Prime Time of Your Life");
// etc
matrix.Add(track);

但是,为什么您要这样做而不是构建自己的类来表示具有轨道ID,名称,艺术家,专辑,播放计数和跳过计数属性的轨道呢?然后就来吧List<Track>


1
嗯,老实说,我不确定该怎么做!我考虑单独设置一个用于播放列表处理的类,但是我想这是一个更好的主意。
2009年

另外,它是否不要求知道我最终将创建/存储多少个曲目?
2009年

2
否,因为List <Track>仍是动态大小。你会分析数据的一个轨道,轨道创建一个新实例,将其添加到列表<跟踪>,然后解析下一个,等等
乔恩斯基特

在caspert中,List <T>会跟踪它为您存储的对象数量。您可以通过致电List <T> .Count
Spoike

3
@CasperT请完成许多建议并Track上课。了解/维护代码将更加容易。如果将轨道表示为字符串列表,则必须在尝试访问轨道信息的所有实例之间同步存储特定属性的索引。每次实现都会变得很乏味,并且无法调试。为了您自己,请上课。:)
Alexander Kondratskiy 2011年

103

正如乔恩·斯基特(Jon Skeet)所提到的,您可以List<Track>改为使用a 。Track类如下所示:

public class Track {
    public int TrackID { get; set; }
    public string Name { get; set; }
    public string Artist { get; set; }
    public string Album { get; set; }
    public int PlayCount { get; set; }
    public int SkipCount { get; set; }
}

要创建一个曲目列表,List<Track>您只需执行以下操作:

var trackList = new List<Track>();

添加曲目可以像这样简单:

trackList.add( new Track {
    TrackID = 1234,
    Name = "I'm Gonna Be (500 Miles)",
    Artist = "The Proclaimers",
    Album = "Finest",
    PlayCount = 10,
    SkipCount = 1
});

可以使用索引运算符来访问轨道:

Track firstTrack = trackList[0];

希望这可以帮助。


4
如果您想真正地精通,Track也可以是一个结构。;)
Spoike

3
不符合您提供的定义...结构的实例大小应小于16bytes ...
Ian

@伊恩:嗯。我没有意识到这一点。快速检查了MSDN文档,发现结构需要小于16个字节。感谢您指出。
Spoike

14
他们并不需要是,它只是一个建议。其实并不重要。如果需要值语义,请选择struct,否则请选择class。如果您不知道,请使用课程。
杰森

@Spoike:如果要在迭代过程中添加某行中的数据,如何在2 for循环中使用列表。例如:for(i=0;i< length; i++) { for(j=0;j<length2;j++) {// what should be written here to get the values from a 2d array // to this 2d list } }
Sandeep

35

这是我发现的最简单的方法。

List<List<String>> matrix= new List<List<String>>(); //Creates new nested List
matrix.Add(new List<String>()); //Adds new sub List
matrix[0].Add("2349"); //Add values to the sub List at index 0
matrix[0].Add("The Prime of Your Life");
matrix[0].Add("Daft Punk");
matrix[0].Add("Human After All");
matrix[0].Add("3");
matrix[0].Add("2");

检索值甚至更容易

string title = matrix[0][1]; //Retrieve value at index 1 from sub List at index 0

4
尽管先前关于Track类的建议最适合OP的要求,但是THIS解决方案对我来说是构建二维对象网格的最佳解决方案。谢谢!
CigarDoug

2
是的,这是我发现的最简单,最优雅的解决方案,很高兴得到我的帮助!
Jordan LaPrise 2014年

1
简单而有用!谢谢!
Dov Miller

12

我使用过的另一项工作是...

List<int []> itemIDs = new List<int[]>();

itemIDs.Add( new int[2] { 101, 202 } );

我正在使用的库有一个非常正式的类结构,并且我不想在那儿多余的东西有效地记录了两个“相关” int的特权。

依靠程序员仅输入2个项目的数组,但由于它不是常见项目,我认为它可以工作。


2

您也可以通过这种方式

List<List<Object>> Parent=new  List<List<Object>>();

List<Object> Child=new List<Object>();
child.Add(2349);
child.Add("Daft Punk");
child.Add("Human");
.
.
Parent.Add(child);

如果您需要另一个子项,则创建一个新的子项实例,

Child=new List<Object>();
child.Add(2323);
child.Add("asds");
child.Add("jshds");
.
.
Parent.Add(child);

2

这是制作二维列表的方法

        // Generating lists in a loop.
        List<List<string>> biglist = new List<List<string>>();

        for(int i = 1; i <= 10; i++)
        {
            List<string> list1 = new List<string>();
            biglist.Add(list1);
        }

        // Populating the lists
        for (int i = 0; i < 10; i++)
        {
            for(int j = 0; j < 10; j++)
            {
                biglist[i].Add((i).ToString() + " " + j.ToString());
            }
        }

        textbox1.Text = biglist[5][9] + "\n";

请注意访问未填充位置的危险。


1

我用了:

List<List<String>> List1 = new List<List<String>>
var List<int> = new List<int>();
List.add("Test");
List.add("Test2");
List1.add(List);
var List<int> = new List<int>();
List.add("Test3");
List1.add(List);

等于:

List1
(
[0] => List2 // List1[0][x]
    (
        [0] => Test  // List[0][0] etc.
        [1] => Test2

    )
[1] => List2
    (
        [0] => Test3

这对我有帮助!谢谢!
Dov Miller

0

您还可以使用DataTable-您可以定义列数及其类型,然后添加行 http://www.dotnetperls.com/datatable


只需将DataSource添加到您的类型中,以支持代码中的强类型类,并易于在数据网格视图中配置轨迹的可视化,则可以更好地坚持该List<Track>方法并使用。BindingSourceDataGridViewTrack
奥利弗·

同意,但是有时您不想立即显示数据,也不想再创建一个仅在一个地方使用它的类,因此我更喜欢使用现有的解决方案。...只是想指出另一种解决方法!;)
2013年

0

这是我前几天为正在开发的游戏引擎所做的一些操作。它用作本地对象变量的持有人。基本上,您将其用作普通列表,但它将值保留在字符串名称为(或ID)的位置。进行一些修改,您将获得2D列表。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace GameEngineInterpreter
{
    public class VariableList<T>
    {
        private List<string> list1;
        private List<T> list2;

        /// <summary>
        /// Initialize a new Variable List
        /// </summary>
        public VariableList()
        {
            list1 = new List<string>();
            list2 = new List<T>();
        }

        /// <summary>
        /// Set the value of a variable. If the variable does not exist, then it is created
        /// </summary>
        /// <param name="variable">Name or ID of the variable</param>
        /// <param name="value">The value of the variable</param>
        public void Set(string variable, T value)
        {
            if (!list1.Contains(variable))
            {
                list1.Add(variable);
                list2.Add(value);
            }
            else
            {
                list2[list1.IndexOf(variable)] = value;
            }
        }

        /// <summary>
        /// Remove the variable if it exists
        /// </summary>
        /// <param name="variable">Name or ID of the variable</param>
        public void Remove(string variable)
        {
            if (list1.Contains(variable))
            {
                list2.RemoveAt(list1.IndexOf(variable));
                list1.RemoveAt(list1.IndexOf(variable));
            }
        }

        /// <summary>
        /// Clears the variable list
        /// </summary>
        public void Clear()
        {
            list1.Clear();
            list2.Clear();
        }

        /// <summary>
        /// Get the value of the variable if it exists
        /// </summary>
        /// <param name="variable">Name or ID of the variable</param>
        /// <returns>Value</returns>
        public T Get(string variable)
        {
            if (list1.Contains(variable))
            {
                return (list2[list1.IndexOf(variable)]);
            }
            else
            {
                return default(T);
            }
        }

        /// <summary>
        /// Get a string list of all the variables 
        /// </summary>
        /// <returns>List string</string></returns>
        public List<string> GetList()
        {
            return (list1);
        }
    }
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.