Минимальное значение из двух массивов для создания нового массива

Я обновлял свои навыки программирования на 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.

Я буду очень признателен за информацию о том, что может происходить на заднем плане. Заранее спасибо :)

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
0
671
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Я бы сделал массив из двух элементов с заданным индексом, отфильтровал бы 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);

А, хороший улов, спасибо. Нужна дополнительная проверка, чтобы увидеть, пуст ли отфильтрованный массив или нет.

CertainPerformance 13.12.2020 22:45

Вы можете проверить значение и соответствующее значение из второго массива и получить минимальное значение либо значения, либо очень большого значения.

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);

Мне нравится твой подход. Простой и элегантный.

Anthony 14.12.2020 11:56
Ответ принят как подходящий

Конкретная ошибка, которую вы видите в выводе, связана с тем, что вы используете 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. Спасибо, что нашли время объяснить, что происходит. Я ценю тебя. Ваше здоровье!

Anthony 14.12.2020 06:14

этот подход не является симметричным, потому что, если вы поменяете местами два массива, вы получите другой результат, который выглядит нежелательным. основная проблема заключается в единственной проверке нуля одного массива, а не обоих, что усложнило бы обратный вызов. 7 1 1 4 1 2 1 1 0 против 0 1 1 0 1 2 1 0 0

Nina Scholz 14.12.2020 12:16

Согласен @NinaScholz, я отредактирую, чтобы отметить проблему - логика в вашем ответе чиста и решает проблему, но вы не объяснили, почему код OP устранял ошибки, которые были.

pilchard 14.12.2020 12:36

Сначала вычислите 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)

Другие вопросы по теме