Я обновлял свои навыки программирования на JavaScript и обнаружил интересное поведение.
У меня есть два массива, и я хочу создать новый массив, который будет состоять только из наименьшего ненулевого значения из каждого из индексов двух массивов. Например:
// input
A = [1,3,5]
B = [0,2,6]
//expected
C = [1,2,5]
// for every index, the smallest value is chosen, as long as it is not a 0
Я хотел использовать array.map()
, чтобы решить эту проблему.
Это был мой вклад:
const array1 = [7,2,1,4,1,2,1,1,0];
const array2 = [0,1,1,0,1,2,1,0,0];
const result = array1.map(x => array2[array1.indexOf(x)] == 0? x:Math.min(x,array2[array1.indexOf(x)]));
// expected
// [7, 1, 1, 4, 1, 2, 1, 1, 0]
// Actual output
[7, 1, 1, 4, 1, 1, 1, 1, 0]
Как видите, ожидаемое значение по индексу 5
должно быть 2
, но вместо этого я получаю 1
.
Я буду очень признателен за информацию о том, что может происходить на заднем плане. Заранее спасибо :)
Я бы сделал массив из двух элементов с заданным индексом, отфильтровал бы 0, а затем распространил бы на Math.min
.
Поскольку вы хотите разрешить нули только в том случае, если все элементы в массиве равны 0, я бы выделил логику в отдельную функцию, которая возвращает [0]
, если все элементы равны 0, или массив отфильтрованных элементов в противном случае:
const A = [1, 3, 5, 0];
const B = [0, 2, 6, 0];
const sanitize = arr => {
const filtered = arr.filter(n => n !== 0);
return filtered.length ? filtered : [0];
};
const result = A.map((a, i) => Math.min(
...sanitize([a, B[i]])
));
console.info(result);
Вы можете проверить значение и соответствующее значение из второго массива и получить минимальное значение либо значения, либо очень большого значения.
const
array1 = [7, 2, 1, 4, 1, 2, 1, 1, 0],
array2 = [0, 1, 1, 0, 1, 2, 1, 0, 0],
result = array1.map((v, i) =>
(v || array2[i]) &&
Math.min(v || Number.MAX_VALUE, array2[i] || Number.MAX_VALUE)
);
console.info(...result);
Более краткий подход, взглянув на нулевые значения
const
getMin = (a, b) => a === 0 && b || b === 0 && a || Math.min(a, b),
array1 = [7, 2, 1, 4, 1, 2, 1, 1, 0],
array2 = [0, 1, 1, 0, 1, 2, 1, 0, 0],
result = array1.map((v, i) => getMin(v, array2[i]));
console.info(...result);
Мне нравится твой подход. Простой и элегантный.
Конкретная ошибка, которую вы видите в выводе, связана с тем, что вы используете indexOf(). Я думаю, вы ожидаете, что indexOf(x)
вернет индекс текущего итерируемого элемента, но на самом деле он возвращает первый индекс, по которому найдено эквивалентное значение. Это означает, что вы не сравниваете правильные значения.
Это список индексов, которые вы тестируете в своем примере:
array1[0] to array2[0]
array1[1] to array2[1]
array1[2] to array2[2]
array1[3] to array2[3]
array1[4] to array2[2] // mismatch
array1[5] to array2[1] // mismatch
array1[6] to array2[2] // mismatch
array1[7] to array2[2] // mismatch
array1[8] to array2[8]
(На самом деле просто удивительно, что у вас была только одна аномалия в выводе).
Если вы вместо этого используете index
, переданный map()
, ваш метод возвращает ожидаемый результат в этом случае.
Но, как заметила Нина в комментариях, ваша логика несимметрична и вернет разные результаты, если вы перевернете массивы. Ответ Нины обеспечивает чистое решение этой проблемы.
const array1 = [7,2,1,4,1,2,1,1,0];
const array2 = [0,1,1,0,1,2,1,0,0];
function minByIndex(a, b) {
return a.map((x, i) => b[i] === 0 ? x : Math.min(x,b[i]));
}
// expected
// [7, 1, 1, 4, 1, 2, 1, 1, 0]
console.info(...minByIndex(array1, array2));
// [7, 1, 1, 4, 1, 2, 1, 1, 0]
// non-symmetrical output
console.info(...minByIndex(array2, array1));
// [0, 1, 1, 0, 1, 2, 1, 0, 0]
Спасибо! Я сам был очень удивлен таким поведением! Это был почти год без программирования на JS. Спасибо, что нашли время объяснить, что происходит. Я ценю тебя. Ваше здоровье!
этот подход не является симметричным, потому что, если вы поменяете местами два массива, вы получите другой результат, который выглядит нежелательным. основная проблема заключается в единственной проверке нуля одного массива, а не обоих, что усложнило бы обратный вызов. 7 1 1 4 1 2 1 1 0
против 0 1 1 0 1 2 1 0 0
Согласен @NinaScholz, я отредактирую, чтобы отметить проблему - логика в вашем ответе чиста и решает проблему, но вы не объяснили, почему код OP устранял ошибки, которые были.
Сначала вычислите min
двух значений, если значение равно 0
, получите max
этих значений.
A = [1, 3, 5, 0, 0];
B = [0, 2, 6, 0, 1];
const res = A.map((a, i) => Math.min(a, B[i]) || Math.max(a, B[i]));
console.info(res)
А, хороший улов, спасибо. Нужна дополнительная проверка, чтобы увидеть, пуст ли отфильтрованный массив или нет.