JavaScript - String.split (), но для массивов? - PullRequest
0 голосов
/ 05 декабря 2018

Допустим, у меня есть этот массив строк (это HTML-элементы, но мы можем использовать строки для простоты):

["something", "else", "and", "d", "more", "things", "in", "the", "d", "array", "etc"]

Мне нужен быстрый способ разбить этот массив на "d".Вроде как String.split(), кроме массивов.Конечный результат должен выглядеть примерно так:

[["something", "else", "and"], ["more", "things", "in", "the"], ["array", "etc"]]

Есть ли для этого простые однострочные?Может быть, есть функция, встроенная в JS, и я просто скучаю по ней?

Ответы [ 9 ]

0 голосов
/ 05 декабря 2018

Вы можете создать довольно элегантную рекурсивную функцию, например:

let arr = ["something", "else", "and", "d", "more", "things", "in", "the", "d", "array", "etc"]

const spliton = (v, arr, i = arr.indexOf(v)) => (i < 0) 
    ? [arr]
    : [arr.slice(0, i), ...spliton(v, arr.slice(i+1))]


console.log(spliton('d', arr))
0 голосов
/ 05 декабря 2018

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

const None =
  Symbol ()

const prepend = (xs, x) =>
 [ x ] .concat (xs)

const split = (f, [ x = None, ...xs ], then = prepend) =>
  x === None
    ? then ([], [])
    : split
        ( f
        , xs
        , (l, r) =>
            f (x)
              ? then (prepend (l, r), [])
              : then (l, prepend (r, x))
        )

const data = 
  [ 'something', 'else', 'and', 'd', 'more', 'things', 'in', 'the', 'd', 'array', 'etc' ]

console .log
  ( split (x => x === 'd', data)
  )

// [ [ 'something', 'else', 'and' ]
// , [ 'more', 'things', 'in', 'the' ]
// , [ 'array', 'etc' ]
// ]

И оптимизация, которая работает для любого массива input

const prepend = (xs, x) =>
 [ x ] .concat (xs)

const split = (f, xs = [], i = 0, then = prepend) =>
  i >= xs.length
    ? then ([], [])
    : split
        ( f
        , xs
        , i + 1
        , (l, r) =>
            f (xs[i])
              ? then (prepend (l, r), [])
              : then (l, prepend (r, xs[i]))
        )

const data = 
  [ 'something', 'else', 'and', 'd', 'more', 'things', 'in', 'the', 'd', 'array', 'etc' ]

console .log
  ( split (x => x === 'd', data)
  )

// [ [ 'something', 'else', 'and' ]
// , [ 'more', 'things', 'in', 'the' ]
// , [ 'array', 'etc' ]
// ]

Обе реализации O (n) .

0 голосов
/ 05 декабря 2018

Ну, если вам нужен однострочный текст, то вы идете:

var myArray = ["something", "else", "and", "d", "more", "things", "in", "the", "d", "array", "etc"];

const result = myArray.reduce((a, c) => c === "d" ? (a.arr[++a.i] = []) && a : a.arr[a.i].push(c) && a, {arr: [[]], i: 0}).arr;

console.log(result);
0 голосов
/ 05 декабря 2018

Если вас не волнует мутирующий массив, это тоже довольно тривиально с while и Array.shift:

let r = [[]], data = ["something", "else", "and", "d", "more", "things", "in", "the", "d", "array", "etc"]

while(data.length) {
  let item = data.shift()
  item != 'd' ? r[r.length-1].push(item) : r.push([]) 
}

console.log(r)

И если вы это сделаете, то еще короче с Array.reduce:

let arr = ["something", "else", "and", "d", "more", "things", "in", "the", "d", "array", "etc"]

let f = arr.reduce((r,c) => (c!='d' ? r[r.length-1].push(c) : r.push([]),r),[[]])

console.log(f)

Идея в обоих случаях состоит в том, чтобы начать с [[]], и тогда единственная проверка, которая вам нужна, это если текущий элемент итерации равен d, и если это так, нажмите newмассив или нажмите на r[r.length-1], который является предыдущим sub array.

0 голосов
/ 05 декабря 2018

Чтобы ответить на ваш вопрос, на ум не приходит краткая однострочная строка, но вы можете выполнить то, что вы хотите, всего несколькими строками кода, перебирая значения и если слово не 'd' сохранить его;если это так, то создайте новый массив для хранения следующего не-d значения:

const words = ["something", "else", "and", "d", "more", "things", "in", "the", "d", "array", "etc"]

let grouped = words.reduce((response,word)=>{
  if (word!=='d')
    response[response.length-1].push(word)
  else
    response[response.length]=[]
  return response
},[[]])

console.log(grouped)
0 голосов
/ 05 декабря 2018

Достаточно простого forEach подхода.

var arr = ["something", "else", "and", "d", "more", "things", "in", "the", "d", "array", "etc"];
var result = [], temp = [];

arr.forEach(function(elem, index){
    elem !=='d' ? temp.push(elem) : (result.push(temp), temp = []);
    index==arr.length-1 && (result.push(temp));
});

console.log(result)
0 голосов
/ 05 декабря 2018

let myArray = ["something", "else", "and", "d", "more", "things", "in", "the", "d", "array", "etc"];
let splitArray = [],
    tempArray = [];
myArray.forEach((ele, index) => {
    if(ele !== 'd') {
      tempArray.push(ele);
    }
    if(ele === 'd' || index === myArray.length - 1) {
      splitArray.push(tempArray);
      tempArray = []; 
    }
})

console.log(': ', splitArray);
0 голосов
/ 05 декабря 2018

Используйте уменьшение, начиная с аккумулятора, в котором есть массив, содержащий пустой массив.Если текущим элементом является разделенное значение, добавьте дополнительный пустой массив в конец, в противном случае распределите последний массив с текущим элементом.

const arr = ["something", "else", "and", "d", "more", "things", "in", "the", "d", "array", "etc"];

const splitArray = (array, val) =>
  array && array.length
    ? array.reduce(
        (results, item) =>
          item === val
            ? [...results, []]
            : [...results.filter((_, i) => i < results.length - 1), [...results[results.length - 1], item]],
        [[]]
      )
    : array;
  
  
console.log(splitArray(arr, 'd'));
0 голосов
/ 05 декабря 2018

Один из вариантов - объединить пробелы, затем разделить на ' d ', а затем разделить каждый подмассив на пробелы:

const input = ["something", "else", "and", "d", "more", "things", "in", "the", "d", "array", "etc"];
const output = input
  .join(' ')
  .split(' d ')
  .map(str => str.split(' '));
console.log(output);

Или, без объединения, вычислить индекс каждого d и slice каждой секции ввода вокруг d s:

const input = ["something", "else", "and", "d", "more", "things", "in", "the", "d", "array", "etc"];
const dIndicies = input.reduce((a, item, i) => {
  if (item === 'd') a.push(i);
  return a;
}, []);
const output = dIndicies.reduce((a, dIndex, i, arr) => {
  const nextDIndex = arr[i + 1];
  a.push(input.slice(dIndex + 1, nextDIndex));
  return a;
}, [input.slice(0, dIndicies[0] - 1)]);
console.log(output);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...