Gostaria de saber se existe um método mais simples no lodash para substituir um item em uma coleção JavaScript? (Possível duplicado, mas eu não entendi a resposta lá :)
Eu olhei para a documentação deles, mas não consegui encontrar nada
Meu código é:
var arr = [{id: 1, name: "Person 1"}, {id:2, name:"Person 2"}];
// Can following code be reduced to something like _.XX(arr, {id:1}, {id:1, name: "New Name"});
_.each(arr, function(a, idx){
if(a.id === 1){
arr[idx] = {id:1, name: "Person New Name"};
return false;
}
});
_.each(arr, function(a){
document.write(a.name);
});
Atualização: o objeto que estou tentando substituir possui muitas propriedades, como
{id: 1, Prop1: ..., Prop2: ... e assim por diante}
Solução:
Graças ao dfsq, mas encontrei uma solução adequada no lodash que parece funcionar bem e é bem legal e eu a coloquei em um mixin também, pois tenho esse requisito em muitos lugares. JSBin
var update = function(arr, key, newval) {
var match = _.find(arr, key);
if(match)
_.merge(match, newval);
else
arr.push(newval);
};
_.mixin({ '$update': update });
var arr = [{id: 1, name: "Person 1"}, {id:2, name:"Person 2"}];
_.$update(arr, {id:1}, {id:1, name: "New Val"});
document.write(JSON.stringify(arr));
Solução mais rápida Como apontado por @dfsq, seguir é muito mais rápido
var upsert = function (arr, key, newval) {
var match = _.find(arr, key);
if(match){
var index = _.indexOf(arr, _.find(arr, key));
arr.splice(index, 1, newval);
} else {
arr.push(newval);
}
};
javascript
lodash
Vishal Seth
fonte
fonte
_.findIndex
para combinar._.findIndex
vez de_.find
deixará cair o segundo_.find
e o_.indexOf
. Você é a iteração através da matriz 3 vezes quando tudo que você precisa é de 1.Respostas:
No seu caso, tudo o que você precisa fazer é encontrar o objeto na matriz e usar o
Array.prototype.splice()
método, leia mais detalhes aqui :fonte
indexOf
será muito rápida (ela usará os navegadores nativos Array.prototype.indexOf). De qualquer forma, fico feliz em encontrar uma solução que funcione para você._.findIndex
? Então você não precisa usar_.indexOf
.Parece que a solução mais simples seria usar o ES6
.map
ou o lodash_.map
:Isso tem o bom efeito de evitar a mutação da matriz original.
fonte
[ES6] Este código funciona para mim.
fonte
updatedItem
array se não incluir um item com o mesmoid
.Agora vamos testar o desempenho para todos os métodos:
Mostrar snippet de código
fonte
Você também pode usar o findIndex e escolher para obter o mesmo resultado:
fonte
Com o passar do tempo, você deve adotar uma abordagem mais funcional na qual evite mutações nos dados e escreva pequenas funções de responsabilidade única. Com o padrão ECMAScript 6, você pode desfrutar de paradigma de programação funcional em JavaScript com as fornecidas
map
,filter
ereduce
métodos. Você não precisa de outro lodash, sublinhado ou o que mais fazer as coisas mais básicas.Abaixo, incluí algumas soluções propostas para esse problema, a fim de mostrar como esse problema pode ser resolvido usando diferentes recursos de linguagem:
Usando o mapa ES6:
Versão recursiva - equivalente ao mapeamento:
Requer desestruturação e propagação da matriz .
Quando a ordem da matriz final não é importante, você pode usar uma estrutura de dados
object
como HashMap . Muito útil se você já possui uma coleção com chaveobject
- caso contrário, é necessário alterar sua representação primeiro.Requer propagação do restante do objeto , nomes de propriedades calculadas e Object.entries .
fonte
Se você está apenas tentando substituir uma propriedade, lodash
_.find
e_.set
deve ser suficiente:fonte
Se o ponto de inserção do novo objeto não precisar corresponder ao índice do objeto anterior, a maneira mais simples de fazer isso com o lodash é usando
_.reject
e pressionando novos valores na matriz:Se você tiver vários valores que deseja substituir em uma passagem, faça o seguinte (gravado no formato não-ES6):
fonte
Usando a função lodash unionWith, você pode realizar um upsert simples em um objeto. A documentação afirma que, se houver uma correspondência, ela usará a primeira matriz. Coloque seu objeto atualizado em [] (array) e coloque-o como o primeiro array da função union. Simplesmente especifique sua lógica de correspondência e, se encontrada, a substituirá e, se não, a adicionará
Exemplo:
fonte
Variante não é ruim também)
fonte
fonte
Se você está procurando uma maneira de alterar imutável a coleção (como eu estava quando encontrei sua pergunta), você pode dar uma olhada no immutability-helper , uma biblioteca bifurcada no utilitário React original. No seu caso, você realizaria o que mencionou através do seguinte:
fonte
Você pode fazer isso sem usar o lodash.
fonte
Imutável , adequado para
ReactJS
:Presumir:
O item atualizado é o segundo e o nome é alterado para
Special Person
:Dica : o lodash tem ferramentas úteis, mas agora temos alguns deles em Ecmascript6 +, então eu só usar
map
função que é existia em amboslodash
eecmascript6+
:fonte
Também deparei com isso e fez isso simplesmente dessa maneira.
Se desejado, podemos generalizá-lo
fonte