Разделить список шаблонов на основе заданного префикса - PullRequest
0 голосов
/ 18 ноября 2018

У меня есть упорядоченный список таких строк, где правая цифра «-» может увеличиваться до любого числа.

let arr = ['1-0/2-0/3-0', '1-0/2-0/3-1', '1-0/2-1/3-0', '1-1/2-0/3-0', '1-1/2-1/3-0', '1-1/2-1/3-1', '1-1/2-2/3-0']

Я хочу извлечь их в массив / список на основе некоторого префикса и сгруппировать их по прямой цифре после префикса.

Например, 1: если задан префикс 1-, то выходной массив должен содержать две записи

[['1-0/2-0/3-0', '1-0/2-0/3-1', '1-0/2-1/3-0'], ['1-1/2-0/3-0', '1-1/2-1/3-0', '1-1/2-1/3-1', '1-1/2-2/3-0']]

Например, 2: если задан префикс 1-1/2-, то выходной массив должен содержать три записи

[['1-1/2-0/3-0'], ['1-1/2-1/3-0', '1-1/2-1/3-1'], ['1-1/2-2/3-0']]

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

Ответы [ 3 ]

0 голосов
/ 18 ноября 2018

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

let list = ["1-0/2-0/3-0","1-0/2-0/3-1","1-0/2-1/3-0","1-1/2-0/3-0","1-1/2-1/3-0","1-1/2-1/3-1","1-1/2-2/3-0"]

function segregate(prefix, list){
   return Object.values(
     list.filter(str => str.startsWith(prefix))
     .reduce((obj, str) => {
       let key = str[prefix.length]
       if (!obj[key]) obj[key] = []
       obj[key].push(str)
       return obj
     }, {})
   )

}

console.log("with '1-'")
console.log(segregate("1-", list))

console.log("with '1-1/2-'")
console.log(segregate("1-1/2-", list))
0 голосов
/ 18 ноября 2018

Другое возможное решение - создать дерево из префиксов, которое выглядит следующим образом:

{
    '1': {
    letters: ['1-0/2-0/3-0',
              '1-0/2-0/3-1',
              '1-0/2-1/3-0', ...]
    children: {
        '0/2': {
        letters: [...],
        children: {
          ...
        }
      }
      ...
    }
  }
}

Затем, используя префикс, мы можем пройти по этому дереву, чтобы найти соответствующие группы букв. Этот подход имеет лучшее время выполнения, так как вам не нужно просматривать весь список префиксов (при условии, что он намного больше, чем «глубина» префиксов):

const strings = [
  '1-0/2-0/3-0',
  '1-0/2-0/3-1',
  '1-0/2-1/3-0',
  '1-1/2-0/3-0',
  '1-1/2-1/3-0',
  '1-1/2-1/3-1',
  '1-1/2-2/3-0'
]

function insert(path, letter, tree) {
  if (path.length > 0) {
    let [node, ...remaining] = path;
    if (node in tree) tree[node].letters.push(letter);
    else tree[node] = {children: {}, letters: [letter]};
    insert(remaining, letter, tree[node].children);
  }
}

const prefixTree = strings.reduce((acc, curr) => {
  insert(curr.split('-'), curr, acc);
  return acc;
}, {});


function getLetters(prefix) {
  function get(path, tree) {
    if (path.length === 1)
      return Object.values(tree[path[0]].children)
                   .map(v => v.letters);
    return get(path.slice(1), tree[path[0]].children);
  }
  return get(prefix.split('-').filter(s => s !== ''), prefixTree);
}

console.log(getLetters('1-'));
console.log(getLetters('1-1/2-'));

console.log('Prefix tree looks like the following');
console.log(prefixTree);
0 голосов
/ 18 ноября 2018

Предположим, у вас просто есть массив предметов. Затем легко выполнить сопоставление префиксов с помощью startsWith:

const filtered = arr.filter(a => a.startsWith(prefix))

Тогда похоже, что вы группируете до первого / после префикса. Вы можете использовать reduce для этого, но groupBy в lodash делает это очень легко. Рабочий пример:

const arr = [
  '1-0/2-0/3-0',
  '1-0/2-0/3-1',
  '1-0/2-1/3-0',
  '1-1/2-0/3-0',
  '1-1/2-1/3-0',
  '1-1/2-1/3-1',
  '1-1/2-2/3-0'
]

const prefix = '1-1/2-'

const filtered = arr.filter(a => a.startsWith(prefix))
const groups = _.groupBy(filtered, i => i.slice(prefix.length).split('/')[0])
const values = _.values(groups)
console.log(values)
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.10/lodash.min.js"></script>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...