Get object in array by description in index

4

Is it possible to use the property of an object as an index of an array , as described in the example below?

using System;

public class Program
{
    public static void Main()
    {
        var myObjectArray = new MyObject[]{
            new MyObject("item1", "valor1", 1, 1.1),
            new MyObject("item2", "valor2", 2, 2.2),
            new MyObject("item3", "valor3", 3, 3.3)
        };

        // Para obter o valor do objeto com o Name "item2", preciso encontra-lo através do índice:
        Console.WriteLine(myObjectArray[1].Value);

        // O que eu gostaria de fazer é passar o valor da propriedade 'Name' de um determinado objeto como index, 
        // e poder acessar todas as propriedades dele, da seguinte forma:
        Console.WriteLine(myObjectArray["item2"].Value);
    }
}

public class MyObject {
    public string Name {get; set;}
    public string Value {get; set;}
    public int Prop1 {get; set;}
    public double Prop2 {get; set;}

    public MyObject (string name, string valueParam, int prop1, double prop2){
        this.Name = name;
        this.Value = valueParam;
        this.Prop1 = prop1;
        this.Prop2 = prop2;
    }
}

dotnetfiddle

    
asked by anonymous 24.11.2017 / 12:53

5 answers

4

It seems to me that a dictionary is enough for what do you need?

using System;
using System.Collections.Generic;

public class Program {
    public static void Main() {
        var dicionario = new Dictionary<string, MyObject> {
            ["item1"] = new MyObject("item1", "valor1", 1, 1.1),
            ["item2"] = new MyObject("item2", "valor2", 2, 2.2),
            ["item3"] = new MyObject("item3", "valor3", 3, 3.3)
        };
        Console.WriteLine(dicionario["item2"].Value);
    }
}

public class MyObject {
    public string Name {get; set;}
    public string Value {get; set;}
    public int Prop1 {get; set;}
    public double Prop2 {get; set;}

    public MyObject (string name, string valueParam, int prop1, double prop2){
        this.Name = name;
        this.Value = valueParam;
        this.Prop1 = prop1;
        this.Prop2 = prop2;
    }
}

See running on .NET Fiddle . And in Coding Ground . Also I placed GitHub for future reference .

The dictionary has almost identical access time to the array , (at least the access complexity is essentially the same (O (1) in a typical case, but O (N) , which in practice never really comes close to happening).

It is important to note that if you list all elements they can come in any order and if you try to get an element by its index may not see what you are expecting, the algorithm is not stable to give this possibility, even if it works in a basic test will not work otherwise, and the same test that worked may no longer work if you change the Dictionary or the hash algorithm of the object used as the key. There is no guarantee of anything.

If you need to order use a SortedDictionary . It is slightly slower but in most cases changes very little and there are many cases that it may be faster than the dictionary. It has complexity O (logN) which is very close to O (1). There are cases where the hash formula may add overhaed which makes it worse than accessing the SortedDictionary tree. The worst case of it is O (logN), so it is much more predictable and avoids certain types of DOS attacks that the hash allows. And because of the impaired reference locale the hash table of the Dictionary can access the data more slowly because it does not take advantage of the cache.

If you have to ensure that key values do not repeat you can use Set , you have some options .

You have another option, KeyedCollection that gives you the advantage of the list and the advantage of the dictionary at the same time, it may be the most appropriate for what you want. It uses one of the object's members as a key implicitly.

    
24.11.2017 / 13:46
2

The easiest would be to add a reference to Linq

using System.Linq;

And make the query according to the attribute you want.

Console.WriteLine(myObjectArray.FirstOrDefault(x => x.Name == "item2").Value);
    
24.11.2017 / 14:02
2
  

Is it possible to use the property of an object as an index of an array, as described in the example below?

YES

I like working with Collection List more. I find it more elegant, and do not need to create an index as in the dictionary, you can use the name of your own object, or ID, as you like.

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

public class Program
{
    public static void Main()
    {
        var minhaColecao = new MinhaCollection();
        minhaColecao.Add(new MeuObjeto { Nome = "A", Valor = 10.0m, Data = DateTime.Now });
        minhaColecao.Add(new MeuObjeto { Nome = "B", Valor = 2.0m, Data = DateTime.Now });
        minhaColecao.Add(new MeuObjeto { Nome = "C", Valor = 340.5m, Data = DateTime.Now });

        var objA = minhaColecao["A"];   

        Console.WriteLine($"Nome: {objA.Nome} Valor: {objA.Valor} ");
    }
}

public class MinhaCollection : List<MeuObjeto>
{
    public MeuObjeto this[string nome]
    {
        get
        {
            return this.FirstOrDefault(meuObjeto => meuObjeto.Nome == nome);
        }
    }
}

public class MeuObjeto
{
    public string Nome { get; set; }
    public decimal Valor { get; set; }
    public DateTime Data { get; set; }
}

See working at .NET Fiddle .

    
24.11.2017 / 14:01
2

What you are looking for is a data structure called Dictionary , it is nothing more than a hash table.

A hash table is a linear data structure with constant access complexity, so there is not much loss of perfomance when exchanging an array by a dictionary . The access of both has complexity O (1). It is clear that inserting into a hash table takes more time than inserting directly into an array , however, using a dictionary there is the advantage of fetching the keys, for you.

You can take advantage of Linq extension methods and access index , as your first example asks.

Note that there is no guarantee that the order of the structure will be the same order of insertion, this is because Dictionary keeps its own ordering.

See an example:

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

public class Program
{
    public static void Main()
    {
        var dicionario = new Dictionary<string, MyObject>()
        {
            { "item1", new MyObject{ Name = "item1", Value = "valor1" } },
            { "item2", new MyObject{ Name = "item2", Value = "valor2" } },
            { "item3", new MyObject{ Name = "item3", Value = "valor3" } }               
        };      

        // Acesso por index:
        Console.WriteLine(dicionario.Values. ElementAt(1));

        // Acesso pela chave
        Console.WriteLine(dicionario["item2"].Value);
    }
}

public class MyObject 
{
    public string Name {get; set;}
    public string Value {get; set;}
    public int Prop1 {get; set;}
    public double Prop2 {get; set;} 
}
    
24.11.2017 / 13:49
1

Do with Dictionary , example :

Base Class:

public class MyObject 
{
    public string Name {get; set;}
    public string Value {get; set;}
    public int Prop1 {get; set;}
    public double Prop2 {get; set;}

    public MyObject (string name, string valueParam, int prop1, double prop2)
    {
        this.Name = name;
        this.Value = valueParam;
        this.Prop1 = prop1;
        this.Prop2 = prop2;
    }
}

Dictionary

Dictionary<string, MyObject> myObjectArray = new Dictionary<string, MyObject>();
myObjectArray.Add("Item1", new MyObject("item1", "valor1", 1, 1.1));
myObjectArray.Add("Item2", new MyObject("item2", "valor2", 2, 2.2));
myObjectArray.Add("Item3", new MyObject("item3", "valor3", 3, 3.3));

Recovery

var dado = myObjectArray["Item1"]

Accessing values :

dado.Name
dado.Value
dado.Prop1
dado.Prop2

An ONLINE sample that you can use as a basis for your code .

24.11.2017 / 13:45