JavaScript: как обрабатывать все последовательные пары элементов? - PullRequest
3 голосов
/ 12 марта 2019

У меня есть массив слов:

["get", "out", "of", "the", "way"]

и функция:

isPrepOrParticle

, который возвращает true для элементов "out" и "of" .

Я бы хотел приклеить все true элементы к предыдущим с подчеркиванием и получить следующее:

["get_out_of", "the", "way"]

Есть ли хороший функциональный способ сделать это, применив какую-то функцию ко всем последовательным кортежам:

f = (a, b) => {
  if (isPrepOrParticle(b)) return a + "_" + b;

  return null;
}

Ответы [ 6 ]

2 голосов
/ 12 марта 2019

Я думаю, reduceRight также предоставляет хороший способ сделать это чисто функциональным способом:

const merge = (words, preps) =>
    words.reduceRight(([b, ...rest], a, i) => 
        preps.has(words[i+1]) ? [a+"_"+b, ...rest] : b ? [a, b, ...rest] : [a], []);

console.log(merge(["get", "out", "of", "the", "way"], new Set(["out", "of"])));
2 голосов
/ 12 марта 2019

Поскольку вам нужно манипулировать массивом и отдельными элементами, я думаю, что Array.reduce - ваш лучший выбор.

var words = ["get", "out", "of", "the", "way"];
var special = ["out", "of"];

var janked = words.reduce((acc, el) => {
  if (special.includes(el) && acc.length) {
    // append underscore + current element to previous element
    acc[acc.length - 1] += "_" + el;
  } else {
    // just add this element to the array
    acc.push(el);
  }
  return acc;
}, []);

console.log(janked);
1 голос
/ 13 марта 2019

Вот еще одно классическое рекурсивное определение, дополняющее программу Джордана.Он написан с использованием выражений вместо утверждений -

const glue = (a = "", b = "", ...rest) =>
  b === ""                      // base: no b
    ? [ a ]
: a === ""                      // inductive: some b, no a
    ? []
: isPrepOrParticiple (b)        // inductive: some b, some a, participle
    ? glue (`${a}_${b}`, ...rest)
: [ a, ...glue (b, ...rest) ]   // inductive: some b, some a, non-participle

const isPrepOrParticiple = word =>
  word === 'out' || word === 'of'

console .log (glue ('get', 'out', 'of', 'the', 'way'))
// [ 'get_out_of', 'the', 'way' ]
1 голос
/ 12 марта 2019

Если вы хотите классическое рекурсивное решение, оно может выглядеть так:

const isPrepOrParticiple = word => word === 'out' || word === 'of';

function glue(a, b, ...rest) {
  if (a) {
    if (b) {
      if (isPrepOrParticiple(b)) {
        return glue(`${a}_${b}`, ...rest);
      }
      return [a, ...glue(b, ...rest)];
    }
    return [a];
  }
  return [];
}

const input = ['get', 'out', 'of', 'the', 'way'];

console.log(glue(...input));
0 голосов
/ 12 марта 2019

Если вам нужно решение, близкое к тому, что есть в вопросе, вы можете просто заставить reduce вернуть строку слов, разделенных символом, таким как ',' (например, "get_out_of,the,way"), а затем split результирующая строка по этому символу:

let result = arr.reduce((a, b) =>
   isPrepOrParticle(b)? a + "_" + b: a + "," + b
).split(",");

Просто убедитесь, что используется символ, не используемый ни одной из строк в массиве arr.

Примечание: В этом решении ожидается, что в arr будет хотя бы один элемент. Вы можете проверить это перед выполнением кода выше.

0 голосов
/ 12 марта 2019

Вы можете использовать уменьшить

Здесь идея

  • Сначала мы инициализируем два свойства объекта final и temp
  • Мы проверяем следующий индекс, если это out или of, мы добавляем текущее значение к temp
  • когда следующий индекс не равен out или of, мы добавляем temp и current value к финалу после объединения с _ и снова устанавливаем temp в пустой массив

let arr = ["get", "out", "of", "the", "way"]

let op = arr.reduce((op,inp,i)=>{
 if( arr[i+1] === 'out' || arr[i+1] === 'of' ){
  op.temp.push(inp)
 } else {
  op.final.push([...op.temp,inp].join('_'))
  op.temp = []
 }
 return op
},{final:[],temp:[]})

console.log(op.final)
...