Javascript: Эффективно ли заменить объект в массиве, который имеет свойство с указанным значением в состоянии с сохранением состояния? - PullRequest
0 голосов
/ 13 апреля 2020

Возможно, этот вопрос уже задавался и отвечался тысячу раз, но я не смог его найти. Извините :(

Для концепции у меня есть следующий массив в javascript (здесь я изображаю сценарий наихудшего случая):

var array1 = [{id: 8, text: "lala"},/* a lot of elements in between,*/ {id: 79, text: "lolo"}]

Теперь я хотел бы заменить элемент, который в настоящее время имеет идентификатор: 79 с Object {randomProperty1: "lulu"}. Я не хочу заменять массив впоследствии, так как я использую его как реактивное свойство в реактивной системе, такой как vuejs, поэтому он должен оставаться в состоянии. Я не могу сделать что-то вроде:

array1 = array1.map(obj=>obj.id===79?{randomProperty1: "lulu"}:obj);

Мой наивный подход заключается в том, чтобы сделать что-то вроде этого:

const elem = array1.find(obj=>obj.id===79);
const index = array1.indexOf(elem);
array1[index] = {randomProperty1: "lulu"}

Но теперь, как я понимаю, мне придется go через мой массив дважды. Учитывая, что у меня есть огромный массив, выполняющий эту операцию каждый раз, когда моя мышь двигается, и, возможно, мне также пришлось пересчитать мой новый объект, я почувствовал бы себя лучше, если бы прошел только один раз через мой массив. В любом другом случае это было бы явно и, возможно, все еще преждевременная оптимизация, но я заинтересован в этом.

Мой подход к мечте будет примерно таким (в псевдокоде):

const elem = array1.find(o=>o.id===79);
elem = {randomProperty1: "lulu"}

Но это очевидно больше не работает, так как теперь это вызов по значению, а не вызов по ссылке.

Последний (немного некрасивый) подход, который я предложил, состоит в том, чтобы полностью изменить мой массив следующим образом:

var array2 = [{obj: {id: 8, text: "lala"}},/* a lot of elements in between,*/ {obj: {id: 79, text: "lolo"}}];
const elem = array2.find(o=>o.obj.id===79);
elem.obj = {randomProperty1: "lulu"}

Короче говоря: есть ли лучший способ сделать это?

PS: я не знаю, это тэг 'vue -реактивность подходит здесь' - я не знаю, если это вещь в angular или реагировать, поскольку я ничего не знаю о те. Мой вопрос возник из vue -реактивности, но я подумал, что это можно обобщить.

Ответы [ 3 ]

1 голос
/ 13 апреля 2020

Используйте findIndex() вместо find()

const index = array1.findIndex(o => o.id === 79);
if (index > -1) {
    array1[index] = {randomProperty1: "lulu"};
}

Кстати, разве новый объект не должен иметь свойство id?

0 голосов
/ 13 апреля 2020

Один прием, который я использовал, когда производительность является главным приоритетом, - это сохранение данных в объекте с массивом цифр c идентификаторов, чтобы отслеживать все.

Пример, подобный вашему:

var arr = [
 { id: 1, text: 'aaa' },
 { id: 2, text: 'bbb' },
 { id: 3, text: 'ccc' },
 { id: 78, text: 'zzz' }
];

var lookup = arr.reduce((prev, next) => {
  prev[next.id] = next;
  prev.allIds.push(next.id);
  return prev;
}, { allIds: [] });

Теперь, если вы знаете идентификатор, который хотите заменить, вам не нужно l oop вообще

lookup[78] = { id: 78, text: 'new!' };

Если вы хотите l oop через массив, используйте свойство allIds

lookup.allIds.forEach(x=> {
  let item = lookup[x];
  item.text = '';
});
0 голосов
/ 13 апреля 2020

Вам не нужно проверять, равен ли индекс -1 или нет. если это -1, когда вы используете ваш массив, он не будет отображаться, вы можете получить к нему доступ только при использовании array1 [-1], но если вы просто консоль log1 array1, он пропускает индекс -1

var array1 = [{id: 8, text: "lala"},{id: 9, text: "lela"},{id: 10, text: "lale"},{id: 11, text: "lalala"}, {id: 79, text: "lolo"}]

array1[array1.findIndex(obj => obj.id === 79)] = {randomProperty1: 'lulu'}
...