Чи можливі двовимірні списки в c #?


89

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

У мене є файл / список файлів, який моя програма зберігає у стандартному списку. Один рядок з файлу в кожному записі списку.

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

Ось дані, які я хочу вставити:

Список
(
    [0] => Список
        (
            [0] => Ідентифікатор треку
            [1] => Ім'я
            [2] => Виконавець
            [3] => Альбом
            [4] => Кількість відтворень
            [5] => Пропустити підрахунок

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

Реальний приклад:

Список
(
    [0] => Список
        (
            [0] => 2349
            [1] => Найкращий час вашого життя
            [2] => Daft Punk
            [3] => Зрештою, людина
            [4] => 3
            [5] => 2

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

Так, так, mlist [0] [0] отримає TrackID з пісні 1, mlist [1] [0] з пісні 2 тощо.

Але у мене виникають величезні проблеми зі створенням багатовимірного списку. Поки що я це придумав

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

Але у мене насправді не було набагато більше прогресу :(

Відповіді:


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);

Але чому ви робите це замість того, щоб створювати власний клас для представлення доріжки із властивостями ідентифікатора доріжки, імені, виконавця, альбому, відтворення та пропуску? Тоді просто мати List<Track>.


1
Хм, я чесно не знаю, як це зробити! Я розглядав створення класу для обробки списків відтворення самостійно, але, мабуть, це краща ідея.
CasperT

Крім того, чи не потрібно буде знати, скільки треків я зрештою створу / збережу?
CasperT 20.03.09

2
Ні, оскільки List <Track> все ще має динамічний розмір. Ви повинні проаналізувати дані для однієї доріжки, створити новий екземпляр Доріжки, додати її до Списку <Track>, а потім проаналізувати наступний тощо
Джон Скіт,

caspert, List <T> відстежує кількість об’єктів, які він зберігає для вас. Ви можете отримати доступ до суми, зателефонувавши List <T>
.Count

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];

Сподіваюся, це допомагає.


4
Якщо ви хочете бути справді кмітливими, Track також може бути структурою. ;)
Spoike 20.03.09

3
Не з визначенням, яке ви дали ... Структури повинні мати розмір екземпляра менше 16 байт ...
Ян

@Ian: Хм. Я цього не знав. Швидко перевіривши MSDN-документ для цього, виявляється, що структури повинні бути менше 16 байт. Дякуємо, що вказали на це.
Spoike 20.03.09

14
Їм цього не потрібно , це лише рекомендація. Це насправді не так важливо; вибирайте struct, якщо вам потрібна семантика значення, інакше просто клас. Якщо ви не знаєте, використовуйте клас.
jason 02

@Spoike: як використовувати список у циклі 2 для циклів, якщо ви хочете додати дані, наявні в якомусь рядку, під час ітерації через цикл. Наприклад: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 } }
Сандіп

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 } );

Бібліотека, над якою я працюю, має дуже офіційну структуру класів, і я не хотів там зайво додавати речі, щоб мати змогу записати два "споріднених" вкладиші.

Покладається на те, що програміст вводить лише масив із 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

Це мені корисно! Дякую!
Дов Міллер

0

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


Краще дотримуйтесь List<Track>підходу та використовуйте a BindingSource, просто додавши DataSource до вашого DataGridViewтипу, Trackщоб підтримувати строко набрані класи в коді та легко налаштовувати візуалізацію доріжок у поданні сітки даних.
Олівер

Погоджено, але іноді ви не хочете миттєво відображати дані і не хочете створювати ще один клас, щоб просто використовувати його лише в одному місці, тому я вважаю за краще використовувати існуюче рішення. ... Просто хотів вказати ще на один спосіб вирішити це! ;)
Валь

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);
        }
    }
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.