Логика, лежащая в основе функции уменьшения и распространения, с использованием одной строки оператора if

#javascript #spread-syntax

#javascript #spread-синтаксис

Вопрос:

У меня возникли проблемы с пониманием оператора if для этого примера сокращения:

 const colors = ['red', 'red', 'green', 'blue', 'green', 'yellow'];
console.log(colors);

const distinctColors = colors.reduce(
    (distinct, color) =>
        (distinct.indexOf(color) !== -1) ? 
            distinct : 
            [...distinct, color], []
)

console.log(distinctColors) 

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

 
If the color found in the distinct array (which is empty)
  return empty array
else
  return contents of array and color added to an empty array

 

Я я близко или далеко?

тестирование repl.it здесь

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

1. distinct пусто только на первой итерации. Более правильным объяснением было бы «Если цвет найден в отдельном массиве, верните отдельный массив. Else возвращает новый массив, содержащий элемент отдельного массива и цвет.». Но на самом деле, вы должны просто использовать const distinctColors = new Set(colors); .

2. Теперь я бы склонялся к использованию Set const distinctColors = [...new Set(colors)]'

3. Этот аргумент для начального значения отформатирован (с отступом) действительно странно.

Ответ №1:

Попытался объяснить с комментариями, надеюсь, это поможет.

 const colors = ['red', 'red', 'green', 'blue', 'green', 'yellow'];
console.log(colors);

const distinctColors = colors.reduce(
    (distinct, color) =>
        (distinct.indexOf(color) !== -1) ? 
        // ----------------^ Turnary to test for presence of current color in the accum []
            distinct : 
        // ----^ It DOES exist, so return the current Accum array    
            [...distinct, color], []
            // ---^ Is DOES NOT exist, return a new array of Accum   Color
            // --------------------^ This initialises a new empty array into the accumulator
)

console.log(distinctColors) 

Просто добавил это для справки, использование set для этого намного эффективнее.

 const colors = ['red', 'red', 'green', 'blue', 'green', 'yellow'];
console.log(colors);

const distinctColors = [...new Set(colors)];

console.log(distinctColors) 

Вот документация MDN по Set. Javascript Set

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

1. Set захватывает разные значения по умолчанию?

2. Это так. Для более сложных объектов вы, скорее всего, будете использовать комбинацию карт. Однако в этом случае вам нужно только передать массив.

Ответ №2:

Это уменьшает массив до его уникальных значений. Вы можете прочитать это как:

Устанавливается distinct в пустой массив (2-й параметр для уменьшения). Для каждого color in colors , если color он находится в distinct (индекс !== -1), обновите distinct до distinct (no-op) (первая троичная ветвь), иначе, если color он не distinct включен, обновите distinct до distinct color (2-я троичная ветвь).

Смотрите документацию mdn reduce .