Pergunta

Eu vi algumas maneiras diferentes para iterar sobre um dicionário em C #. Existe uma maneira padrão?

Foi útil?

Solução

foreach(KeyValuePair<string, string> entry in myDictionary)
{
    // do something with entry.Value or entry.Key
}

Outras dicas

Se você está tentando usar um dicionário genérico em C # como você usaria uma matriz associativa em outro idioma:

foreach(var item in myDictionary)
{
  foo(item.Key);
  bar(item.Value);
}

Ou, se você só precisa iterar sobre a coleção de chaves, uso

foreach(var item in myDictionary.Keys)
{
  foo(item);
}

E por último, se você estiver interessado apenas nos valores:

foreach(var item in myDictionary.Values)
{
  foo(item);
}

(Tome nota que a palavra-chave var é um opcional C # 3.0 e recurso acima, você também pode usar o tipo exato de suas chaves / valores aqui)

Em alguns casos você pode precisar de um contador que pode ser fornecido por implementação para-loop. Para isso, LINQ fornece ElementAt que permite o seguinte:

for (int index = 0; index < dictionary.Count; index++) {
  var item = dictionary.ElementAt(index);
  var itemKey = item.Key;
  var itemValue = item.Value;
}

Depende se você estiver após as chaves ou os valores ...

A partir do MSDN Dictionary(TKey, TValue) Classe Descrição:

// When you use foreach to enumerate dictionary elements,
// the elements are retrieved as KeyValuePair objects.
Console.WriteLine();
foreach( KeyValuePair<string, string> kvp in openWith )
{
    Console.WriteLine("Key = {0}, Value = {1}", 
        kvp.Key, kvp.Value);
}

// To get the values alone, use the Values property.
Dictionary<string, string>.ValueCollection valueColl =
    openWith.Values;

// The elements of the ValueCollection are strongly typed
// with the type that was specified for dictionary values.
Console.WriteLine();
foreach( string s in valueColl )
{
    Console.WriteLine("Value = {0}", s);
}

// To get the keys alone, use the Keys property.
Dictionary<string, string>.KeyCollection keyColl =
    openWith.Keys;

// The elements of the KeyCollection are strongly typed
// with the type that was specified for dictionary keys.
Console.WriteLine();
foreach( string s in keyColl )
{
    Console.WriteLine("Key = {0}", s);
}

Geralmente, pedindo "a melhor maneira" sem um contexto específico é como perguntar o que é a melhor cor ?

Por um lado, há muitas cores e não há melhor cor. Depende da necessidade e muitas vezes no sabor, também.

Por outro lado, há muitas maneiras para iterar sobre um Dicionário em C # e não há melhor maneira. Depende da necessidade e muitas vezes no sabor, também.

A maioria maneira direta
foreach (var kvp in items)
{
    // key is kvp.Key
    doStuff(kvp.Value)
}

Se você precisar apenas o valor (permite chamá-lo item, mais legível do que kvp.Value).

foreach (var item in items.Values)
{
    doStuff(item)
}

Se você precisar de uma ordem específica sort

Geralmente, os novatos são surpreendidos sobre a ordem de enumeração de um dicionário.

LINQ fornece uma sintaxe concisa que permite especificar a ordem (e muitas outras coisas), por exemplo:.

foreach (var kvp in items.OrderBy(kvp => kvp.Key))
{
    // key is kvp.Key
    doStuff(kvp.Value)
}

Mais uma vez você pode só precisa do valor. LINQ também fornece uma solução concisa para:

  • iterate diretamente sobre o valor (permite chamá-lo item, mais legível do que kvp.Value)
  • , mas classificadas pelas teclas

Aqui está:

foreach (var item in items.OrderBy(kvp => kvp.Key).Select(kvp => kvp.Value))
{
    doStuff(item)
}

Há muitos mais casos de uso do mundo real que você pode fazer a partir desses exemplos. Se você não precisa de uma ordem específica, apenas ater à "maneira mais simples" (veja acima)!

Eu diria que foreach é a maneira padrão, embora, obviamente, depende do que você está procurando

foreach(var kvp in my_dictionary) {
  ...
}

É isso que você está procurando?

Você também pode tentar isso em grandes dicionários para processamento multithread.

dictionary
.AsParallel()
.ForAll(pair => 
{ 
    // Process pair.Key and pair.Value here
});

Há uma abundância de opções. O meu favorito é por KeyValuePair

Dictionary<string, object> myDictionary = new Dictionary<string, object>();
// Populate your dictionary here

foreach (KeyValuePair<string,object> kvp in myDictionary)
{
     // Do some interesting things
}

Você também pode usar as chaves e valores coleções

Eu aprecio esta questão já tinha um monte de respostas, mas eu queria jogar um pouco de pesquisa.

iteração sobre um dicionário pode ser um pouco lento quando comparado com a iteração sobre algo como um array. Em meus testes uma iteração sobre um array levou 0.015003 segundos enquanto uma iteração sobre um dicionário (com o mesmo número de elementos) levou 0.0365073 segundos isso é 2,4 vezes mais tempo! Embora eu tenha visto diferenças muito maiores. Para efeito de comparação uma lista estava em algum lugar entre a 0.00215043 segundos.

No entanto, isso é como comparar maçãs e laranjas. Meu ponto é que a iteração sobre dicionários é lento.

Os dicionários são otimizados para pesquisas, então com isso em mente que eu criei dois métodos. Um simplesmente faz um foreach, os outros itera as chaves, em seguida, olha para cima.

public static string Normal(Dictionary<string, string> dictionary)
{
    string value;
    int count = 0;
    foreach (var kvp in dictionary)
    {
        value = kvp.Value;
        count++;
    }

    return "Normal";
}

este cargas as chaves e itera sobre eles, em vez (Eu também tentei puxar as chaves em uma string [], mas a diferença foi insignificante.

public static string Keys(Dictionary<string, string> dictionary)
{
    string value;
    int count = 0;
    foreach (var key in dictionary.Keys)
    {
        value = dictionary[key];
        count++;
    }

    return "Keys";
}

Com este exemplo o teste foreach normal, tomou 0.0310062 ea versão chaves tomou 0,2205441. Carregando todas as chaves e interagindo sobre todas as pesquisas é claramente muito mais lento!

Para um teste final Eu realizada meus iteração dez vezes para ver se existem quaisquer benefícios a usar as chaves aqui (por este ponto eu estava apenas curioso):

Aqui está o método RunTest se isso ajuda a visualizar o que está acontecendo.

private static string RunTest<T>(T dictionary, Func<T, string> function)
{            
    DateTime start = DateTime.Now;
    string name = null;
    for (int i = 0; i < 10; i++)
    {
        name = function(dictionary);
    }
    DateTime end = DateTime.Now;
    var duration = end.Subtract(start);
    return string.Format("{0} took {1} seconds", name, duration.TotalSeconds);
}

Aqui o normal funcionamento foreach levou 0.2820564 segundos (cerca de dez vezes mais do que uma única iteração levou - como seria de esperar). A iteração sobre as teclas levou 2.2249449 segundos.

Editado para acrescentar: Lendo alguns dos outros respostas me fez questionar o que aconteceria se eu usasse dicionário em vez de dicionário. Neste exemplo a matriz levou 0.0120024 segundos, a lista 0.0185037 segundos eo dicionário 0.0465093 segundos. É razoável esperar que o tipo de dados faz a diferença em quanto mais lento o dicionário é.

Quais são as minhas Conclusões ?

  • Evite iteração sobre um dicionário se você pode, eles são substancialmente mais lento do que a iteração sobre um array com os mesmos dados na mesma.
  • Se você optar por iteração sobre um dicionário não tente ser muito inteligente, embora mais lento do que você poderia fazer muito pior do que usando o método foreach padrão.

C # 7.0 introduziu desconstrutores e se você estiver usando .NET Núcleo 2.0 + Aplicação, o KeyValuePair<> struct já incluem um Deconstruct() para você. Então você pode fazer:

var dic = new Dictionary<int, string>() { { 1, "One" }, { 2, "Two" }, { 3, "Three" } };
foreach (var (key, value) in dic) {
    Console.WriteLine($"Item [{key}] = {value}");
}
//Or
foreach (var (_, value) in dic) {
    Console.WriteLine($"Item [NO_ID] = {value}");
}
//Or
foreach ((int key, string value) in dic) {
    Console.WriteLine($"Item [{key}] = {value}");
}

 enter descrição da imagem aqui

Você sugeriu abaixo para iterate

Dictionary<string,object> myDictionary = new Dictionary<string,object>();
//Populate your dictionary here

foreach (KeyValuePair<string,object> kvp in myDictionary) {
    //Do some interesting things;
}

FYI, foreach não funciona se o valor é de tipo de objeto.

Com .NET Framework 4.7 pode-se usar decomposição

var fruits = new Dictionary<string, int>();
...
foreach (var (fruit, number) in fruits)
{
    Console.WriteLine(fruit + ": " + number);
}

Para fazer este trabalho de código em versões menores C #, adicione System.ValueTuple NuGet package e em algum lugar write

public static class MyExtensions
{
    public static void Deconstruct<T1, T2>(this KeyValuePair<T1, T2> tuple,
        out T1 key, out T2 value)
    {
        key = tuple.Key;
        value = tuple.Value;
    }
}

forma mais simples para iterar um dicionário:

foreach(var item in myDictionary)
{ 
    Console.WriteLine(item.Key);
    Console.WriteLine(item.Value);
}

Usando C # 7 , adicione método de extensão para qualquer projeto de sua solução:

public static class IDictionaryExtensions
{
    public static IEnumerable<(TKey, TValue)> Tuples<TKey, TValue>(
        this IDictionary<TKey, TValue> dict)
    {
        foreach (KeyValuePair<TKey, TValue> kvp in dict)
            yield return (kvp.Key, kvp.Value);
    }
}


E usar essa sintaxe simples

foreach (var(id, value) in dict.Tuples())
{
    // your code using 'id' and 'value'
}


Ou este, se você preferir

foreach ((string id, object value) in dict.Tuples())
{
    // your code using 'id' and 'value'
}


No lugar do tradicional

foreach (KeyValuePair<string, object> kvp in dict)
{
    string id = kvp.Key;
    object value = kvp.Value;

    // your code using 'id' and 'value'
}


O método de extensão transforma o KeyValuePair do seu IDictionary<TKey, TValue> em um tuple fortemente tipado, permitindo que você use essa nova sintaxe confortável.

Ele converte -just- as entradas de dicionário necessários para tuples, para que ele não converte todo o dicionário para tuples, para que não haja questões de desempenho relacionadas a isso.

Há um custo único menor de chamar o método de extensão para criar um tuple em comparação com o uso do KeyValuePair diretamente, que não deve ser um problema se você está atribuindo propriedades do KeyValuePair Key e Value a novas variáveis ??de laço de qualquer maneira.

Na prática, este novo ternos de sintaxe muito bem para a maioria dos casos, exceto para cenários de desempenho ultra-alto de baixo nível, onde ainda têm a opção de simplesmente não usá-lo naquele local específico.

Veja isto: MSDN Blog - novos recursos do C # 7

Às vezes, se você só precisa os valores a serem enumerados, usar a coleção de valor do dicionário:

foreach(var value in dictionary.Values)
{
    // do something with entry.Value only
}

Relatado por este post, que afirma que é o método mais rápido: http://alexpinsker.blogspot.hk/2010 /02/c-fastest-way-to-iterate-over.html

Eu encontrei este método na documentação para a classe DictionaryBase no MSDN:

foreach (DictionaryEntry de in myDictionary)
{
     //Do some stuff with de.Value or de.Key
}

Este foi o único que eu era capaz de conseguir funcionando corretamente em uma classe que herdou do DictionaryBase.

Vou ter a vantagem de .NET 4.0+ e fornecer uma resposta atualizado para a originalmente aceitou um:

foreach(var entry in MyDic)
{
    // do something with entry.Value or entry.Key
}

A forma padrão para iterar sobre um dicionário, de acordo com a documentação oficial sobre MSDN é:

foreach (DictionaryEntry entry in myDictionary)
{
     //Read entry.Key and entry.Value here
}

A partir de C # 7, você pode desconstruir objetos em variáveis. Eu acredito que isso seja a melhor maneira de interagir sobre um dicionário.

Exemplo:

Criar um método de extensão em KeyValuePair<TKey, TVal> que desconstrói-lo:

public static void Deconstruct<TKey, TVal>(this KeyValuePair<TKey, TVal> pair, out TKey, out TVal val)
{
   key = pair.Key;
   val = pair.Value;
}

Iterate sobre qualquer Dictionary<TKey, TVal> da seguinte maneira

// Dictionary can be of any types, just using 'int' and 'string' as examples.
Dictionary<int, string> dict = new Dictionary<int, string>();

// Deconstructor gets called here.
foreach (var (key, value) in dict)
{
   Console.WriteLine($"{key} : {value}");
}

Se por exemplo, você quer iterar sobre a coleção de valores por padrão, eu acredito que você pode implementar IEnumerable <>, onde T é o tipo dos valores objeto no dicionário, e "este" é um dicionário.

public new IEnumerator<T> GetEnumerator()
{
   return this.Values.GetEnumerator();
}
var dictionary = new Dictionary<string, int>
{
    { "Key", 12 }
};

var aggregateObjectCollection = dictionary.Select(
    entry => new AggregateObject(entry.Key, entry.Value));

Só queria acrescentar o meu 2 cêntimos, como a maioria das respostas estão relacionadas com foreach-loop. Por favor, dê uma olhada no seguinte código:

Dictionary<String, Double> myProductPrices = new Dictionary<String, Double>();

//Add some entries to the dictionary

myProductPrices.ToList().ForEach(kvP => 
{
    kvP.Value *= 1.15;
    Console.Writeline(String.Format("Product '{0}' has a new price: {1} $", kvp.Key, kvP.Value));
});

Altought isso adiciona uma chamada adicional de '.ToList ()', pode haver uma ligeira desempenho de melhoria (como apontado aqui foreach vs someList.Foreach () {} ), espacially quando se trabalha com grandes dicionários e funcionando em paralelo há opção / não terá um efeito.

Além disso, observe que você não será capaz de valores Atribuir para a propriedade 'valor' dentro de um foreach-loop. Por outro lado, você será capaz de manipular o 'Key', bem como, possivelmente, ficando-lhe problemas em tempo de execução.

Quando você quer apenas "ler" chaves e valores, que você pode também usar IEnumerable.Select ().

var newProductPrices = myProductPrices.Select(kvp => new { Name = kvp.Key, Price = kvp.Value * 1.15 } );

Eu escrevi uma extensão de varrer um dicionário.

public static class DictionaryExtension
{
    public static void ForEach<T1, T2>(this Dictionary<T1, T2> dictionary, Action<T1, T2> action) {
        foreach(KeyValuePair<T1, T2> keyValue in dictionary) {
            action(keyValue.Key, keyValue.Value);
        }
    }
}

Em seguida, você pode chamar

myDictionary.ForEach((x,y) => Console.WriteLine(x + " - " + y));

Eu sei que esta é uma questão muito antiga, mas eu criei alguns métodos de extensão que podem ser úteis:

    public static void ForEach<T, U>(this Dictionary<T, U> d, Action<KeyValuePair<T, U>> a)
    {
        foreach (KeyValuePair<T, U> p in d) { a(p); }
    }

    public static void ForEach<T, U>(this Dictionary<T, U>.KeyCollection k, Action<T> a)
    {
        foreach (T t in k) { a(t); }
    }

    public static void ForEach<T, U>(this Dictionary<T, U>.ValueCollection v, Action<U> a)
    {
        foreach (U u in v) { a(u); }
    }

Desta forma, eu posso escrever código como este:

myDictionary.ForEach(pair => Console.Write($"key: {pair.Key}, value: {pair.Value}"));
myDictionary.Keys.ForEach(key => Console.Write(key););
myDictionary.Values.ForEach(value => Console.Write(value););

Dictionary É uma classe de coleção genérica em c # e ele armazena os dados no format.Key chave valor deve ser único e não pode ser nulo enquanto que o valor pode ser duplicado e null.As cada item no dicionário é tratado como KeyValuePair estrutura que representa uma chave e seu valor. e, portanto, devemos tomar o tipo de elemento KeyValuePair durante a iteração do elemento. Segue-se o exemplo.

Dictionary<int, string> dict = new Dictionary<int, string>();
dict.Add(1,"One");
dict.Add(2,"Two");
dict.Add(3,"Three");

foreach (KeyValuePair<int, string> item in dict)
{
    Console.WriteLine("Key: {0}, Value: {1}", item.Key, item.Value);
}

Além dos postos mais elevados do ranking, onde há uma discussão entre usando

foreach(KeyValuePair<string, string> entry in myDictionary)
{
    // do something with entry.Value or entry.Key
}

ou

foreach(var entry in myDictionary)
{
    // do something with entry.Value or entry.Key
}

mais completa é a seguinte porque você pode ver o tipo de dicionário a partir do inicialização, kvp é KeyValuePair

var myDictionary = new Dictionary<string, string>(x);//fill dictionary with x

foreach(var kvp in myDictionary)//iterate over dictionary
{
    // do something with kvp.Value or kvp.Key
}

Os dicionários são listas especiais, ao passo que cada valor na lista tem uma chave o qual é também uma variável. Um bom exemplo de um dicionário é um livro de telefone.

   Dictionary<string, long> phonebook = new Dictionary<string, long>();
    phonebook.Add("Alex", 4154346543);
    phonebook["Jessica"] = 4159484588;

Observe que ao definir um dicionário, precisamos fornecer um genérico definição com dois tipos - o tipo da chave e o tipo do valor. Neste caso, a chave é uma string enquanto o valor é um inteiro.

Há também duas maneiras de adicionar um valor único para o dicionário, quer usando o operador de colchetes ou usando o método Add.

Para verificar se um dicionário tem uma certa chave nele, podemos usar o método ContainsKey:

Dictionary<string, long> phonebook = new Dictionary<string, long>();
phonebook.Add("Alex", 415434543);
phonebook["Jessica"] = 415984588;

if (phonebook.ContainsKey("Alex"))
{
    Console.WriteLine("Alex's number is " + phonebook["Alex"]);
}

Para remover um item de um dicionário, podemos usar o método Remove. Removendo um item de um dicionário por sua chave é rápido e muito eficiente. Ao remover um item de uma lista usando o seu valor, o processo é lento e ineficiente, ao contrário do dicionário Remove função.

Dictionary<string, long> phonebook = new Dictionary<string, long>();
phonebook.Add("Alex", 415434543);
phonebook["Jessica"] = 415984588;

phonebook.Remove("Jessica");
Console.WriteLine(phonebook.Count);
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top