Então, eu tenho uma lista genérica, e um oldIndex
e um newIndex
valor.
Quero mover o item em oldIndex
, para newIndex
... o mais simples possível.
Alguma sugestão?
Nota
O item deve terminar entre os itens antes(newIndex - 1)
e newIndex
depois da remoção.
newIndex--
não resulta no comportamento que você disse que queria.ObservableCollection
e não é genéricoList<T>
, mas é trivial simplesmente trocar as chamadas de método para obter o mesmo resultado.[newIndex - 1]
e[newIndex]
não é invertível.Move(1, 3); Move(3, 1);
não retorna a lista ao estado inicial. Enquanto isso, há um comportamento diferente fornecidoObservableCollection
e mencionado nesta resposta , que é invertível .Respostas:
Eu sei que você disse "lista genérica", mas não especificou que precisava usar a classe List (T), então aqui está uma amostra de algo diferente.
A classe ObservableCollection (T) possui um método Move que faz exatamente o que você deseja.
Por baixo, é basicamente implementado assim.
Portanto, como você pode ver, o método de troca sugerido por outras pessoas é essencialmente o que o ObservableCollection faz em seu próprio método Move.
ATUALIZAÇÃO 30/12/2015: Agora você pode ver o código-fonte dos métodos Move e MoveItem no corefx sem usar o Reflector / ILSpy, pois o .NET é de código aberto.
fonte
fonte
newIndex
realmente interrompe meu teste (veja minha resposta abaixo).lock
declaração.Eu sei que esta pergunta é antiga, mas eu adaptei ESTA resposta do código javascript em C #. Espero que ajude
fonte
List <T> .Remove () e List <T> .RemoveAt () não retornam o item que está sendo removido.
Portanto, você deve usar isto:
fonte
Insira o item atualmente em
oldIndex
estar emnewIndex
e, em seguida, remova a instância original.Você deve levar em consideração que o índice do item que você deseja remover pode mudar devido à inserção.
fonte
Eu criei um método de extensão para mover itens em uma lista.
Um índice não deve mudar se estiver movendo um item existente, pois estamos movendo um item para uma posição de índice existente na lista.
O caso de borda a que o @Oliver se refere abaixo (mover um item para o final da lista) realmente causaria uma falha nos testes, mas isso ocorre por design. Para inserir um novo item no final da lista, basta ligar
List<T>.Add
.list.Move(predicate, list.Count)
deve falhar, pois essa posição de índice não existe antes da movimentação.De qualquer forma, criei dois métodos de extensão adicionais
MoveToEnd
eMoveToBeginning
, cuja fonte pode ser encontrada aqui .fonte
Ensure.Argument
definido?List<T>
você pode ligarInsert(list.Count, element)
para colocar algo no final da lista. Então vocêWhen_new_index_is_higher
deve ligar olist.Move(x => x == 3, 5)
que realmente falha.List<T>
eu chamaria apenas.Add
para inserir um novo item no final de uma lista. Ao mover itens individuais, nunca aumentamos o tamanho original do índice, pois estamos apenas removendo um único item e reinserindo-o. Se você clicar no link na minha resposta, encontrará o código paraEnsure.Argument
.Eu esperaria:
... ou:
... faria o truque, mas não tenho o VS nesta máquina para verificar.
fonte
newIndex
se for depoisoldIndex
.Maneira mais simples:
EDITAR
A questão não é muito clara ... Como não nos importamos para onde o
list[newIndex]
item vai, acho que a maneira mais simples de fazer isso é a seguinte (com ou sem um método de extensão):Esta solução é a mais rápida porque não envolve inserções / remoções de listas.
fonte
São caras mais simples, basta fazer isso
Faça o mesmo com MoveDown, mas altere o if for "if (ind! = Concepts.Count ())" e o Concepts.Insert (ind + 1, item.ToString ());
fonte
Foi assim que implementei um método de extensão de elemento de movimentação. Ele lida muito bem com a movimentação antes / depois e nos extremos dos elementos.
fonte