我有一个这样的字符串有序列表,其中'-'的右边数字可以增加到任何数字。
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']]
我正在寻找一种比暴力破解更好的技巧(例如使用正则表达式)。
答案 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);