Возможны ли двухмерные списки в с #?

89

Я хочу составить многомерный список. Для справки, работаю над анализатором плейлистов.

У меня есть файл / список файлов, который моя программа сохраняет в стандартном списке. Одна строка из файла в каждой записи списка.

Затем я анализирую список с помощью регулярных выражений, чтобы найти конкретные строки. Некоторые данные / результаты из строк необходимо поместить в новый многомерный список; поскольку я не знаю, сколько результатов / данных я получу, я не могу использовать многомерный массив.

Вот данные, которые я хочу вставить:

Список
(
    [0] => Список
        (
            [0] => Идентификатор трека
            [1] => Имя
            [2] => Художник
            [3] => Альбом
            [4] => Счетчик воспроизведений
            [5] => Счетчик пропусков

        )
    [1] => Список
        (
И так далее....

Реальный пример:

Список
(
    [0] => Список
        (
            [0] => 2349
            [1] => Лучшее время в вашей жизни
            [2] => Дафт Панк
            [3] => В конце концов, человек
            [4] => 3
            [5] => 2

        )
    [1] => Список
        (

Так что да, mlist [0] [0] получит TrackID из песни 1, mlist [1] [0] из песни 2 и т. Д.

Но у меня огромные проблемы с созданием многомерного списка. Пока я придумал

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

Но у меня особо не было прогресса :(

CasperT
источник

Ответы:

139

Ну, вы, конечно, можете использовать, List<List<string>>где вы затем напишите:

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

Но зачем вам это делать вместо того, чтобы создавать собственный класс для представления трека со свойствами Track ID, Name, Artist, Album, Play Count и Skip Count? Тогда просто создайте List<Track>.

Джон Скит
источник
1
Хм, я, честно говоря, не знаю, как это сделать! Я рассматривал возможность создания класса только для обработки списков воспроизведения, но я думаю, что это лучшая идея.
CasperT
Кроме того, не потребуется ли знать, сколько треков я в конечном итоге создам / сохраню?
CasperT
2
Нет, потому что List <Track> по-прежнему имеет динамический размер. Вы должны проанализировать данные для одного трека, создать новый экземпляр Track, добавить его в List <Track>, а затем проанализировать следующий и т. Д.
Джон Скит,
caspert, List <T> отслеживает количество объектов, которые он хранит для вас. Вы можете получить доступ к сумме, позвонив в List <T> .Count
Spoike
3
@CasperT Пожалуйста, сделайте то, что многие предлагали, и сделайте Trackкласс. Будет намного проще понять / поддерживать код. Если вы представляете дорожку в виде списка строк, то индексы, в которых вы храните определенный атрибут, должны быть синхронизированы во всех экземплярах, где вы пытаетесь получить доступ к информации о дорожке. Будет утомительно реализовывать каждый раз и невозможно отлаживать. Пожалуйста, ради себя, загляните в классы. :)
Александр Кондрацкий
103

Как сказал Джон Скит, вы можете сделать это с помощью List<Track>. Класс 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];

Надеюсь это поможет.

Spoike
источник
4
Если вы хотите быть действительно подкованным, Track также может быть структурой. ;)
Spoike
3
Не с тем определением, которое вы дали ... Структуры должны иметь размер экземпляра менее 16 байт ...
Ян,
@ Ян: Хм. Я не знал об этом. Быстро проверил документ MSDN для этого, и оказалось, что структуры должны быть меньше 16 байт. Спасибо, что указали на это.
Spoike,
14
Они не должны быть такими, это просто рекомендация. На самом деле это не так уж важно; выберите структуру, если вам нужна семантика значений, иначе просто класс. Если вы не знаете, используйте класс.
Джейсон 02
@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, ЭТО решение является лучшим для меня для построения двумерной сетки объектов. Благодарность!
CigarDoug
2
Да, это самое простое и элегантное решение, и я рад, что помог!
Jordan LaPrise
1
Просто и полезно! Спасибо!
Дов Миллер
12

другая работа, которую я использовал, была ...

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

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

Библиотека, над которой я работаю, имеет очень формальную структуру классов, и мне не нужно было в ней лишних вещей, чтобы получить возможность записать два «связанных» int.

Полагается на то, что программист вводит только массив из двух элементов, но, поскольку это не обычный элемент, я думаю, что он работает.

Пол Джеймисон
источник
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);
DDK
источник
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
СОИАС
источник
Это полезно для меня! Спасибо!
Дов Миллер
0

Вы также можете использовать DataTable - затем вы можете определить количество столбцов и их типы, а затем добавить строки http://www.dotnetperls.com/datatable

Вал
источник
Лучше придерживаться List<Track>подхода и использовать BindingSource, просто добавив DataSource к вашему DataGridViewтипу, Trackчтобы поддерживать строго типизированные классы в коде и легко настраивать визуализацию дорожек в представлении сетки данных.
Оливер
Согласен, но иногда вы не хотите отображать данные мгновенно и не хотите создавать еще один класс, чтобы использовать его только в одном месте, поэтому я предпочитаю использовать существующее решение. ... Просто хотел указать еще один способ решить эту проблему! ;)
Val
0

Вот кое-что, что я сделал некоторое время назад для игрового движка, над которым работал. Он использовался как держатель переменной локального объекта. По сути, вы используете его как обычный список, но он содержит значение в позиции того, что когда-либо было именем строки (или идентификатором). Немного модифицируйте, и у вас будет свой 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);
        }
    }
}
Джо Хоррелл
источник