Listas bidimensionais são possíveis em c #?

89

Eu gostaria de criar uma lista multidimensional. Para referência, estou trabalhando em um analisador de lista de reprodução.

Eu tenho um arquivo / lista de arquivos, que meu programa salva em uma lista padrão. Uma linha do arquivo em cada entrada da lista.

Em seguida, analiso a lista com expressões regulares para encontrar linhas específicas. Alguns dos dados / resultados das linhas precisam ser colocados em uma nova lista multidimensional ; como não sei com quantos resultados / dados vou acabar, não posso usar um array multidimensional.

Aqui estão os dados que desejo inserir:

Lista
(
    [0] => Lista
        (
            [0] => ID da faixa
            [1] => Nome
            [2] => Artista
            [3] => Álbum
            [4] => Contagem de reprodução
            [5] => Contagem de pulos

        )
    [1] => Lista
        (
E assim por diante....

Exemplo real:

Lista
(
    [0] => Lista
        (
            [0] => 2349
            [1] => O melhor momento da sua vida
            [2] => Daft Punk
            [3] => Humano Afinal
            [4] => 3
            [5] => 2

        )
    [1] => Lista
        (

Então, sim, mlist [0] [0] obteria TrackID da música 1, mlist [1] [0] da música 2 etc.

Mas estou tendo grandes problemas para criar uma lista multidimensional. Até agora eu vim com

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

Mas eu realmente não tive muito progresso :(

CasperT
fonte

Respostas:

137

Bem, você certamente pode usar um List<List<string>>onde escreveria:

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

Mas por que você faria isso em vez de criar sua própria classe para representar uma faixa, com as propriedades Track ID, Name, Artist, Album, Play Count e Skip Count? Então é só tomar um List<Track>.

Jon Skeet
fonte
1
Hmm, honestamente não tenho certeza de como fazer isso! Pensei em criar uma classe apenas para lidar com a lista de reprodução, mas acho que é uma ideia melhor.
CasperT de
Além disso, não seria necessário saber quantas faixas irei criar / armazenar?
CasperT de
2
Não, porque List <Track> ainda é dimensionado dinamicamente. Você analisaria os dados de uma trilha, criaria uma nova instância da trilha, adicionaria à lista <Track> e, em seguida, analisaria a próxima, etc.
Jon Skeet
caspert, o List <T> mantém registro da quantidade de objetos que armazena para você. Você pode acessar o valor ligando para List <T> .Count
Spoike
3
@CasperT Por favor, faça o que muitos sugeriram e faça uma Trackaula. Será muito mais fácil entender / manter o código. Se você representar uma trilha como uma lista de strings, então os indeces onde você armazena um determinado atributo terão que ser sincronizados em todas as instâncias onde você tenta acessar as informações da trilha. Será tedioso para implementar todas as vezes e impossível de depurar. Por favor, para seu próprio bem, analise as classes. :)
Alexander Kondratskiy
103

Como Jon Skeet mencionou, você pode fazer isso com um List<Track>. A classe Track seria mais ou menos assim:

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

E para criar uma lista de trilhas como um, List<Track>basta fazer o seguinte:

var trackList = new List<Track>();

Adicionar faixas pode ser tão simples quanto isto:

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

O acesso às faixas pode ser feito com o operador de indexação:

Track firstTrack = trackList[0];

Espero que isto ajude.

Spoike
fonte
4
Se você quiser ser realmente experiente, Track também pode ser uma estrutura. ;)
Spoike,
3
Não com a definição que você deu ... Structs devem ter um tamanho de instância inferior a 16 bytes ...
Ian
@Ian: Hmm. Eu não estava ciente disso. Verifiquei rapidamente o documento do MSDN para isso e descobri que as estruturas precisam ter menos de 16 bytes. Obrigado por apontar isso.
Spoike,
14
Eles não precisam ser, é apenas uma recomendação. Realmente não importa muito; escolha struct se precisar de semântica de valor, caso contrário, apenas class. Se você não sabe, use uma classe.
Jason
@Spoike: como usar a lista dentro de 2 loops for se você quiser adicionar os dados presentes em alguma linha enquanto iterando através do loop. Por exemplo: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

Esta é a maneira mais fácil que encontrei de fazer isso.

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

Recuperar valores é ainda mais fácil

string title = matrix[0][1]; //Retrieve value at index 1 from sub List at index 0
Jordan LaPrise
fonte
4
Embora a sugestão anterior sobre uma classe Track fosse melhor para os requisitos do OP, ESTA solução é a melhor para eu construir uma grade bidimensional de objetos. Obrigado!
CigarDoug de
2
Sim, é o que eu descobri ser a solução mais simples e elegante, fico feliz por ter ajudado!
Jordan LaPrise
1
Simples e útil! Obrigado!
Dov Miller
12

outro trabalho em torno do qual usei foi ...

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

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

A biblioteca na qual estou trabalhando tem uma estrutura de classes muito formal e eu não queria material extra lá para ter o privilégio de gravar dois ints 'relacionados'.

Depende do programador inserir apenas uma matriz de 2 itens, mas como não é um item comum, acho que funciona.

paul Jamison
fonte
2

Você também pode ... fazer desta forma,

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

se você precisar de outro item (filho), crie uma nova instância de filho,

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

Aqui está como fazer uma lista bidimensional

        // 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";

Esteja ciente do perigo de acessar um local não povoado.

Ben
fonte
1

Eu usei:

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

isso é igual a:

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

    )
[1] => List2
    (
        [0] => Test3
SoIAS
fonte
Isso é útil para mim! Obrigado!
Dov Miller
0

Você também pode usar DataTable - você pode definir o número de colunas e seus tipos e, em seguida, adicionar linhas http://www.dotnetperls.com/datatable

Val
fonte
Melhor seguir a List<Track>abordagem e usar um BindingSource, simplesmente adicionando um DataSource ao seu, DataGridViewdo tipo Trackpara suportar classes fortemente tipadas no código e fácil de configurar a visualização das trilhas dentro da visão da grade de dados.
Oliver
Concordo, mas às vezes você não deseja exibir os dados instantaneamente e não deseja criar mais uma classe apenas para usá-la em apenas um lugar, então prefiro usar uma solução existente. ... Só queria apontar mais uma forma de resolver isso! ;)
Val
0

Aqui está uma coisinha que fiz um tempo atrás para um motor de jogo em que estava trabalhando. Foi usado como um portador de variável de objeto local. Basicamente, você a usa como uma lista normal, mas ela mantém o valor na posição do nome da string (ou ID). Uma pequena modificação e você terá sua lista 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);
        }
    }
}
Joe Horrell
fonte