根据给定的前缀隔离模式列表

时间:2018-11-17 23:15:46

标签: javascript regex string permutation

我有一个这样的字符串有序列表,其中'-'的右边数字可以增加到任何数字。

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 :(得分:1)

这是使用普通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))

答案 1 :(得分:0)

让我们假设您只是有一组项目。然后,使用startsWith即可轻松执行前缀匹配:

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

然后,您似乎将分组到前缀后面的第一个/。您可以使用reduce来执行此操作,但是lodash中的groupBy使其非常容易。工作示例:

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>

答案 2 :(得分:0)

另一种可能的解决方案是根据如下所示的前缀创建树:

{
    '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);