Обновление массива по разным индексам с одинаковым значением за один раз

#javascript

#javascript

Вопрос:

Допустим, у меня есть массив a = [8, 3, true, 9, false] и массив индексов b = [1, 3, 4] . Возможно ли сделать что-то подобное:

 a[b] = false;
 

Так что a становится [8, false, true, false, false] ?

Комментарии:

1. Не напрямую, нет. Вы можете использовать forEach : b.forEach(idx => a[idx] = false); или аналогичный

Ответ №1:

Этот синтаксис здесь не будет работать, поскольку b это массив, JS попытается преобразовать b в примитив, вызвав toString() этот массив. Поскольку b.toString() результаты "1,3,4" будут получены, вы в конечном итоге добавите "1,3,4" в качестве свойства в свой массив:

 const a = [8, 3, true, 9, false];
const b = [1, 3, 4];

a[b] = false; // adds property "1,3,4" to the array `a`, sets it to false
console.log(a["1,3,4"]); // false 

Вам нужно будет вручную перебирать индексы в b , и для каждого индекса установите для этого индекса значение a false. Это можно сделать с помощью обычного цикла for или forEach() :

 const a = [8, 3, true, 9, false];
const b = [1, 3, 4];

b.forEach(idx => a[idx] = false);
console.log(a); // [8, false, true, false, false] 

Если вы хотите сохранить это неизменным и не изменять исходный массив, одной из идей может быть использование Object.assign() для объединения и перезаписи индексов, указанных в b :

 const a = [8, 3, true, 9, false];
const b = [1, 3, 4];

const res = Object.assign([], a, ...b.map(idx => ({[idx]: false})));
console.log(res); 

Ответ №2:

В языке нет встроенной поддержки, но вы можете легко написать функцию для этого.

 const at = (ii, y) => (x, i) => ii.includes(i) ? y : x;
 

Это функция curried, которая принимает список индексов ii и новое значение y для этих индексов. Затем он возвращает функцию, которая принимает значение x и индекс i . Если i принадлежит ii , то возвращает новое значение y , в противном случае сохраняет значение x .

Это позволяет удобно встроить его при отображении массива:

 [8, 3, true, 9, false].map(at([1, 3, 4], false));
//  ^        ^  ^
//  1        3  4
//
//=> [8, false, true, false, false]
 

Если вы хотите иметь возможность присваивать разные значения разным индексам, мы можем использовать следующую структуру данных:

 [[xi, xv], [yi, yv], [zi, zv], ...] 
 

Он представляет собой список пар, где первый элемент представляет индекс, а второй элемент представляет новое значение.

Для поддержки этого нам нужно переписать at .

Для каждого (x, i) он пытается найти пару, где 1-й el. равно i . Если есть результат, верните пару, в противном случае верните временную пару [, x] . Наконец, получите доступ ко 2-му элементу пары, который будет значением по этому индексу.

 const at = (...ys) => (x, i) => (ys.find(([j]) => j === i) || [, x])[1];
 

Мы все еще можем встроить его, как указано выше:

 [8, 3, true, 9, false].map(at([1, 'x'], [3, 'y'], [4, 'z']));
//  ^        ^  ^
//  1        3  4
//  x        y  z
//
// [8, "x", true, "y", "z"]