Estou usando um Dictionary<string, int>
onde o int
é uma contagem da chave.
Agora, preciso acessar a última chave inserida dentro do dicionário, mas não sei o nome dela. A tentativa óbvia:
int LastCount = mydict[mydict.keys[mydict.keys.Count]];
não funciona, porque Dictionary.Keys
não implementa um índice [].
Eu só me pergunto se existe alguma classe semelhante? Pensei em usar uma pilha, mas isso apenas armazena uma string. Agora eu poderia criar minha própria estrutura e, em seguida, usar a Stack<MyStruct>
, mas gostaria de saber se existe outra alternativa, essencialmente um dicionário que implemente um indexador [] nas chaves?
c#
.net
dictionary
Michael Stum
fonte
fonte
Respostas:
Como o @Falanwe aponta em um comentário, fazer algo assim está incorreto :
Você não deve depender da ordem das chaves em um dicionário. Se você precisar fazer um pedido, use um OrderedDictionary , conforme sugerido nesta resposta . As outras respostas nesta página também são interessantes.
fonte
HashTable
System.Collections.ICollection 'não contém uma definição para' ElementAt 'e nenhum método de extensão' ElementAt 'que aceita um primeiro argumento do tipo' System.Collections.ICollection 'pode ser encontradoElementAtOrDefault
versão para trabalhar com a versão sem exceção.Dictionary<TKey,TValue>
documentação declara "A ordem das chaves noDictionary<TKey, TValue>.KeyCollection
não é especificada". A fim de ser indefinido, você não tem nenhuma maneira de saber com certeza que está na última posição (mydict.Count -1
)Você pode usar um OrderedDictionary .
fonte
Um dicionário é uma tabela de hash; portanto, você não tem idéia da ordem de inserção!
Se você quiser saber a última chave inserida, sugiro que estenda o Dicionário para incluir um valor LastKeyInserted.
Por exemplo:
Você terá problemas, no entanto, quando usar
.Remove()
isso para superar isso, precisará manter uma lista ordenada das chaves inseridas.fonte
Por que você apenas não estende a classe do dicionário para adicionar uma última propriedade inserida na chave. Algo como o seguinte, talvez?
fonte
Você sempre pode fazer isso:
Mas eu não recomendaria. Não há garantia de que a última chave inserida esteja no final da matriz. A encomenda de chaves no MSDN não é especificada e está sujeita a alterações. Em meu teste muito breve, parece estar em ordem de inserção, mas é melhor você criar uma contabilidade apropriada como uma pilha - como você sugere (embora eu não veja a necessidade de uma estrutura com base no seu outras instruções) - ou cache de variável única, se você precisar apenas conhecer a chave mais recente.
fonte
Eu acho que você pode fazer algo assim, a sintaxe pode estar errada, não usa C # há algum tempo Para obter o último item
ou use Max em vez de Last para obter o valor máximo, não sei qual deles se encaixa melhor no seu código.
fonte
Eu concordo com a segunda parte da resposta de Patrick. Mesmo que em alguns testes pareça manter a ordem de inserção, a documentação (e o comportamento normal de dicionários e hashes) declara explicitamente que a ordem não é especificada.
Você está apenas pedindo problemas, dependendo da ordem das chaves. Adicione sua própria contabilidade (como Patrick disse, apenas uma única variável para a última chave adicionada) para ter certeza. Além disso, não fique tentado com todos os métodos como Last e Max no dicionário, pois provavelmente estão em relação ao comparador de chaves (não tenho certeza disso).
fonte
Caso você decida usar um código perigoso que esteja sujeito a quebra, essa função de extensão buscará uma chave de
Dictionary<K,V>
acordo com a indexação interna (que atualmente para Mono e .NET parece estar na mesma ordem que você, enumerando aKeys
propriedade )É muito preferível usar o Linq:,
dict.Keys.ElementAt(i)
mas essa função irá iterar O (N); o seguinte é O (1), mas com uma penalidade no desempenho da reflexão.fonte
Uma alternativa seria um KeyedCollection se a chave estiver incorporada no valor.
Basta criar uma implementação básica em uma classe selada para usar.
Portanto, para substituir
Dictionary<string, int>
(o que não é um exemplo muito bom, pois não há uma chave clara para um int).fonte
A maneira como você formulou a pergunta me leva a acreditar que o int no Dicionário contém a "posição" do item no Dicionário. A julgar pela afirmação de que as chaves não são armazenadas na ordem em que foram adicionadas, se isso estiver correto, isso significaria que as chaves. sempre ser o número da última chave digitada?
Se estiver correto, existe algum motivo para você não usar o Dictionary <int, string> para poder usar mydict [mydict.Keys.Count]?
fonte
Não sei se isso funcionaria porque tenho certeza de que as chaves não estão armazenadas na ordem em que foram adicionadas, mas você pode converter o KeysCollection em uma Lista e obter a última chave na lista ... mas valeria a pena dar uma olhada.
A única outra coisa em que consigo pensar é armazenar as chaves em uma lista de pesquisa e adicioná-las à lista antes de adicioná-las ao dicionário ... não é bem assim.
fonte
Para expandir a postagem de Daniels e seus comentários sobre a chave, já que a chave está incorporada ao valor de qualquer maneira, você pode usar a
KeyValuePair<TKey, TValue>
como valor. O principal raciocínio para isso é que, em geral, a Chave não é necessariamente derivada diretamente do valor.Então ficaria assim:
Para usar isso como no exemplo anterior, você faria:
fonte
Um dicionário pode não ser muito intuitivo para usar o índice como referência, mas você pode ter operações semelhantes com uma matriz de KeyValuePair :
ex.
KeyValuePair<string, string>[] filters;
fonte
Você também pode usar SortedList e seu equivalente genérico. Essas duas classes e na resposta de Andrew Peters mencionada OrderedDictionary são classes de dicionário nas quais os itens podem ser acessados por índice (posição) e por chave. Como usar essas classes, você pode encontrar: Classe SortedList , Classe Genérica SortedList .
fonte
O UserVoice do Visual Studio fornece um link para a implementação genérica do OrderedDictionary por dotmore.
Mas se você precisar obter apenas pares de chave / valor por índice e não precisar obter valores por chave, use um truque simples. Declare alguma classe genérica (eu a chamei de ListArray) da seguinte maneira:
Você também pode declarar isso com construtores:
Por exemplo, você lê alguns pares de chave / valor de um arquivo e deseja armazená-los na ordem em que foram lidos, para obtê-los posteriormente pelo índice:
Como você deve ter notado, você pode não ter necessariamente apenas pares de chave / valor no seu ListArray. As matrizes de itens podem ter qualquer comprimento, como na matriz irregular.
fonte