Как динамически разделить массив? - PullRequest
0 голосов
/ 02 февраля 2019

У меня есть массив строк, вроде этого:

["x", "foo", "y", "bar", "baz", "z", "0"]

И мне нужно разделить массив для каждого X, Y и Z или других специальных ключевых слов, которые есть.

Я пытался разделить массивы с помощью [x,y,z].split(y), но я уверен, что split() только для строк.

Ключевые слова ( x , y и z ) должны быть первыми в массиве.Как я могу это сделать?

Вот что я пытаюсь получить:

[
    ["x", "foo"],
    ["y", "bar", "baz"],
    ["z", "0"]
]

Ответы [ 10 ]

0 голосов
/ 05 февраля 2019

Довольно просто!

const arr = ["x", "foo", "y", "bar", "baz", "z", "0"];
const specialChar = ['x', 'y', 'z'];
let result = [];

arr.forEach((el, index) => {
  if(specialChar.includes(el)){
    result.push([el, arr[index + 1]])
  }
});

console.log(result)
0 голосов
/ 02 февраля 2019

Я опоздал, но я покажу совершенно другой подход, чем другие ответы.При таком подходе входной массив преобразуется в строку с использованием join(), а результат получается, используя, в основном, регулярные выражения с методом split():

const input = ["x", "foo", "y", "bar", "baz", "z", "0"];
const keyRegex = /(?=#x#)|(?=#y#)|(?=#z#)/;

let res = ("#" + input.join("#") + "#")          // #x#foo#y#bar#baz#z#0#"
    .split(keyRegex)                             // [#x#foo, #y#bar#baz, #z#0#]
    .map(str => str.split("#").filter(Boolean));

console.log(JSON.stringify(res));

А вот еще один подход, использующий map() над массивом с keys.Примечание. Я передал копию массива input методу map и использовал его в качестве аргумента this.Кроме того, я использую splice() над this, чтобы удалить уже проанализированный раздел и выполнить фьючерсы findIndex() над укороченным массивом.Однако ничто из этого не может быть лучше, чем решение с reduce() или стандартным loop над входным массивом.

const input = ["x", "foo", "y", "bar", "baz", "z", "0"];
const keys = ["x", "y", "z"];

let res = keys.map(function(k, i)
{
    let a = this.findIndex(x => x === k);
    let b = this.findIndex(x => x === keys[i+1]);
    return this.splice(a, b >= 0 ? b : this.length);
}, input.slice());

console.log(JSON.stringify(res));
0 голосов
/ 03 февраля 2019
const input = ['x', 'foo', 'y', 'bar', 'baz', 'z', '0'];
const keywords = ['x', 'y', 'z'];

input.reduce((prev, val) => {
    const split = keywords.includes(val);
    const index = prev.length - Number(!split);
    prev[index] = split ? [val] : prev[index].concat(val)
    return prev;
}, []);

Это функциональный способ разделения и избежания нежелательных побочных эффектов.

0 голосов
/ 02 февраля 2019

Вы можете сделать это с помощью этого кода:

function separator(a) {
  var result = [];

  for (var i = 0; i < a.length; i++) {
    var index = a[i].trim().toLowerCase();

    switch (index) {
      case "x":
      case "y":
      case "z":
        if (result[index] == undefined) {
          result.push([index]);
        }
        break;

      default:
        result[result.length - 1].push(a[i]);
    }
  }

  return result;
}

// Sample:
var arr = ["x", "foo", "y", "bar", "baz", "z", "0"];
console.log(separator(arr));

// Result must be:
// [["x", "foo"], ["y", "bar", "baz"], ["z", "0"]]

Или использовать это для группировки:

function separator(a) {
  var result = {};
  var lastIndex = "";

  for (var i = 0; i < a.length; i++) {
    var index = a[i].trim().toLowerCase();

    switch (index) {
      case "x":
      case "y":
      case "z":
        if (result[index] == undefined) {
          result[index] = [];
        }
        lastIndex = index;
        break;

      default:
        result[lastIndex].push(a[i]);
    }
  }

  return result;
}

// Sample:
var arr = ["x", "foo", "y", "bar", "baz", "z", "0"];
console.log(separator(arr));

// Result must be:
// {"x": ["foo"], "y": ["bar", "baz"], "z": ["0"]}

Второй код может работать с расширенным массивом следующим образом:

["x", "foo", "y", "bar", "x", "baz", "z", "0", "y", "bar2"]

And result is this:
{"x": ["foo", "baz"], "y": ["bar", "bar2"], "z": ["0"]}
0 голосов
/ 02 февраля 2019

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

const arr = ["x", "foo", "y", "bar", "baz", "z", "0"];
function splitByKeys(...keys){
let splitarr = [];
  for(let i =0; i<keys.length;i++){
   if(i == keys.length -1 ){
     splitarr.push(arr.slice( arr.indexOf(keys[i]) , arr.length));
   }else{
    splitarr.push(arr.slice( arr.indexOf(keys[i]) , arr.indexOf(keys[i+1])));
   }
  }
  return splitarr;
}
console.log(splitByKeys("x", "y", "z"));
0 голосов
/ 02 февраля 2019

С помощью двойного уменьшения можно на первом этапе вычислить индексы каждого ключа, а на втором уменьшить разделить массив:

var arr = ["x", "foo", "y", "bar", "baz", "z", "0"];
var keys = keys = ["x", "y", "z"];

var retVal = arr.reduce(function(acc, ele, idx) {
    if (keys.indexOf(ele) > -1) {
        acc.push(idx);
    }
    return acc;
}, []).reduce(function(acc, ele, idx, a) {
    acc.push(arr.slice(ele, a[idx+1]));
    return acc;
}, []);

console.log(retVal);
0 голосов
/ 02 февраля 2019

Просто еще один способ сделать это.Вы можете использовать slice:

var a = ["x", "foo", "y", "bar", "baz", "z", "0"];
var breakpoints = ['x', 'y', 'z'];
var res = [];
for(var i = 0; i < breakpoints.length - 1; i++) {
  res = res.concat([a.slice(a.indexOf(breakpoints[i]), a.indexOf(breakpoints[i+1]))]);
}
res = res.concat([a.slice(a.indexOf(breakpoints[i]))]);
console.log(res);
0 голосов
/ 02 февраля 2019

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

Используется Array.reduce:

const input = ['x', 'foo', 'y', 'bar', 'baz', 'z', '0'];
const keywords = ['x', 'y', 'z'];

const result = input.reduce((result, value) => {
  keywords.includes(value) ? result.push([value]) : result[result.length - 1].push(value);
  return result;
}, []);

console.log(result);

Обратите внимание, что произойдет сбой, если первый элемент во входном массиве не является ключевым словом (что не должно быть).Вы можете легко изменить условие на keywords.includes(value) || keywords.length === 0 в противном случае.

0 голосов
/ 02 февраля 2019

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

var array = ["x", "foo", "y", "bar", "baz", "z", "0"],
    keys = ["x", "y", "z"],
    result = array.reduce((i => (r, s) => {
        if (s === keys[i]) {
            r.push([]);
            i++;
        }
        r[r.length - 1].push(s);
        return r;
    })(0), []);

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
0 голосов
/ 02 февраля 2019
 const keywords = new Set(["x", "y", "z"]);

 let acc = [];
 const result = [];

 for(const el of array) {
   if(keywords.has(el)) {
     result.push(acc = [el]);
   } else acc.push(el);
 }
...