Карта или плоская карта, которая работает как Array.prototype.join в Javascript

Я нахожу функциональность Array.prototype.join очень полезной, потому что она применяет значение соединения только к «внутренним» соединениям элементов в массиве. Вот так:

['Hey', 'there'].join('-') // Hey-there

Где Array.protoype.map в этом примере выдает «оставшееся» тире:

['Hey', 'there'].map(value => value + '-') // Hey-there-

Я искал лаконичный способ сопоставления массивов без преобразования их в строку, возможно, в новый массив, например:

// Intended behaviour ['Hey', 'there'].mapJoin('-') // ['Hey', '-', 'there']

Я НЕ ищу обязательного решения проблемы, так как я мог бы написать это сам и поместить его где-нибудь в глобальный импорт. Я ищу собственный способ (ES6 в порядке), чтобы выразить это элегантно так что я могу писать это во всех своих проектах.

Поведение ключевого слова "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) для оценки ваших знаний,...
3
0
295
7
Перейти к ответу Данный вопрос помечен как решенный

Ответы 7

Это не совсем красиво или элегантно, но

['Hey', 'there'].reduce(
  (acc, value, i, arr) => (acc.push(value), i < arr.length - 1 ? acc.push('-') : 0, acc),
  [],
)

Альтернативная версия ответа @ AKX.

const data = ['Hey', 'there'];

const output = data.reduce((p, c, i, a) => p.concat(i < a.length -1 ? [c, '-'] : [c]), []);

console.info(output)

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

var array = ['Hey', 'there'],
    separator = '-',
    result = array.join(',' + separator + ',').split(',');
    
console.info(result);

Другое решение - взять новые индексы и заполнить предыдущий индекс разделителем.

var array = ['Hey', 'there'],
    separator = '-',
    result = Object.assign(
        [],
        ...array.map((v, i) => ({ [i * 2 - 1]: separator, [i * 2]: v }))
    );
    
console.info(result);
Ответ принят как подходящий

Вы ищете Рамда вкрапления.

R.intersperse('n', ['ba', 'a', 'a']); //=> ['ba', 'n', 'a', 'n', 'a']

Хотя в обязательном порядке это реализовано.

Вы можете попробовать это

const mapJoin = (arr, joiner) => {  
  return arr.reduce( (curr, t) => curr.concat(t, joiner), []).slice(0, arr.length*2-1)
}

const data = ["Hey", "There"]

console.info(mapJoin(data, "-"))

Простая рекурсивная кодировка

const intersperse = (sep, [ x, ...rest ]) =>
  // base case; return empty result
  x === undefined
    ? []
  
  // one remaining x, return singleton
  : rest.length === 0
    ? [ x ]

  // default case; return pair of x and sep and recur
  : [ x, sep ] .concat (intersperse (sep, rest))
  
  
console.info
  ( intersperse ("~", [])              // []
  , intersperse ("~", [ 1 ])           // [ 1 ]
  , intersperse ("~", [ 1, 2 ])        // [ 1, ~, 2 ]
  , intersperse ("~", [ 1, 2, 3 ])     // [ 1, ~, 2, ~, 3 ]
  , intersperse ("~", [ 1, 2, 3, 4 ])  // [ 1, ~, 2, ~, 3, ~, 4 ]
  )

Вы ищете функцию intersperse, которую легко определить:

const intersperse = (x, ys) => [].concat(...ys.map(y => [x, y])).slice(1);

console.info(intersperse("-", ["Hey", "there"])); // ["Hey", "-", "there"]
console.info(intersperse(0, [1, 2, 3]));          // [1, 0, 2, 0, 3]
console.info(intersperse(0, []));                 // []

В качестве альтернативы вы можете разложить его на более мелкие функции:

const concat = xss => [].concat(...xss);
const concatMap = (f, xs) => concat(xs.map(f));
const intersperse = (x, ys) => concatMap(y => [x, y], ys).slice(1);

console.info(intersperse("-", ["Hey", "there"])); // ["Hey", "-", "there"]
console.info(intersperse(0, [1, 2, 3]));          // [1, 0, 2, 0, 3]
console.info(intersperse(0, []));                 // []

Вы даже можете установить их на Array.prototype:

Object.assign(Array.prototype, {
    concatenate() {
        return [].concat(...this);
    },
    concatMap(f) {
        return this.map(f).concatenate();
    },
    intersperse(x) {
        return this.concatMap(y => [x, y]).slice(1);
    }
});

console.info(["Hey", "there"].intersperse("-")); // ["Hey", "-", "there"]
console.info([1, 2, 3].intersperse(0));          // [1, 0, 2, 0, 3]
console.info([].intersperse(0));                 // []

В Haskell вы бы написали это так:

intersperse :: a -> [a] -> [a]
intersperse x = drop 1 . concatMap (\y -> [x, y])

Вы видите сходство?

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