对于
的数组['one', 'one', 'two', 'two', 'three', 'one']
使用模式['one','Two','3']将其转换为
['one', 'two', 'three', 'one', 'two', 'one']
我的想法是
const sortArray = oldArray => {
let newArr = [];
while (newArr < oldArray.length) {
// loop through array
for (let i = 0; i < arr.length; i++) {
// loop through pattern
for (let j = 0; j < pattern.length; j++) {
// match
if (arr[i] === pattern[j]) {
// add item to new array
newArr.push(arr[i]);
// remove item from old array
arr.shift();
} else {
// push item to end of array
arr.push(arr[i]);
// remove item from array
arr.shift()
}
}
}
}
return newArray;
}
我可以使用地图来做到这一点,这是我习惯于解决类似问题的方法,但是当涉及到仅通过具有模式的数组进行迭代时,我会感到非常困惑。有什么建议吗?
有地图,这就是我要做的
let a = ['one', 'one', 'two', 'two', 'three', 'one'];
const printValues = (arr, pattern) => {
let map = {};
let a = [];
arr.forEach((v) => {
if (!map[v]) map[v] = 1;
else map[v]++;
})
while (a.length !== arr.length) {
pattern.forEach((v) => {
if (map[v] > 0) {
a.push(v);
map[v]--;
}
})
}
console.log(a);
}
console.log(printValues(a, ['one', 'two', 'three']))
答案 0 :(得分:2)
这是一种无需使用Set或Object并考虑边缘情况(数组中的项不属于模式的项)的方法。
let items = ['one', 'one', 'two', 'two', 'three', 'one', 'three', 'xyz'];
let pattern = ['one', 'two', 'three'];
const sequence = (items, pattern) => {
let results = [];
// clean up the array
let arr = items.map(item => pattern.includes(item) ? item : '').filter(x => x);
while(arr.length) {
pattern.forEach(x => {
if (arr.includes(x)) {
// add to results
results.push(x);
// remove item from the array
arr.splice(arr.indexOf(x), 1);
}
})
}
return results;
}
sequence(items, pattern);
答案 1 :(得分:1)
我认为您有正确的主意,但您想首先遍历模式数组以保留顺序,然后继续查看oldArray
。在以下解决方案中,我还将使用一组存储已使用的索引。
const oldArray = ['one', 'one', 'two', 'two', 'three', 'one'];
const pattern = ['one', 'two', 'three'];
let newArray = [];
let added = new Set();
while (newArray.length < oldArray.length) {
for (let p of pattern) {
for (let i = 0; i < oldArray.length; i++) {
if (!added.has(i) && oldArray[i] === p) {
added.add(i);
newArray.push(p);
break;
}
}
}
}
console.log(newArray);
答案 2 :(得分:1)
尝试以下方法:
let arr = ['one', 'one', 'two', 'two', 'three', 'one','three'];
let freq = arr.reduce((a,curr)=>{
a[curr] = (a[curr] || 0)+1;
return a;
},{});
let len = Object.keys(freq).length;
let result = [];
let pattern = ["one", "two", "three"];
let i = 0;
while(len){
if(freq[pattern[i]]){
result.push(pattern[i]);
freq[pattern[i]] --;
} else
len--;
i++;
i = i % pattern.length;
}
console.log(result);
答案 3 :(得分:1)
其他答案接近,但如果使用Map,则不需要模式数组。添加密钥的顺序就是可以将其取出的顺序。
您应该改用Map:
const arr = ['one', 'one', 'two', 'two', 'three', 'one'];
const map = arr.reduce(
(result, item) =>
result.set(item, (result.get(item) || []).concat(item)),
new Map(),
);
const transform = (arr) => {
const recur = (arr, result, index, max) => {
if (index === max) {
return result;
}
return recur(
arr,
result.concat(arr.map((item) => item[index])),
index + 1,
max,
);
};
return recur(
arr,
[],
0,
Math.max(...arr.map((item) => item.length)),
).filter((x) => x !== undefined);
};
console.log(transform(Array.from(map.values())));
答案 4 :(得分:1)
这是一个有趣的问题!
注意:您实际上并没有告诉您如何处理模式未知的元素。它们应该全部出现在开头还是结尾,或者分布均匀?我已经决定不去理会。 em>
如果您将模式看作是产生新数组的种子,而不是对现有数组的迭代约束,则此问题更容易解决,恕我直言。
您可以创建一个接受模式以及每个元素的频率的函数:
createFromPattern({one: 3, two: 2, three:1}, ['one', 'two', 'three']);
生成频率很容易:
const count = list => list.reduce((acc, cur) => ({...acc, [cur]: (acc[cur] || 0) + 1}), {});
count(['one', 'one', 'two', 'two', 'three', 'one']);
//=> { one: 3, two: 2, three: 1 }
让我们想象一下该功能的工作原理:
{ one: 3, two: 2, three: 1 }
〜> ['one', 'two', 'three']
{ one: 2, two: 1, three: 0 }
〜> ['one', 'two']
{ one: 1, two: 0, three: -1 }
〜> ['one']
{ one: 0, two: -1, three: -2 }
〜> []
停止 如果汇总每个中间结果,则会得到最终数组。这可以递归完成:
const createFromPattern = (opts, seed) => {
const newOpts = {...opts};
const pick = seed.reduce((acc, cur) => [...acc, ...(newOpts[cur] ? newOpts[cur]-- && [cur] : [])], []);
const stop = Math.max(...Object.values(newOpts)) <= 0;
return [].concat(pick, (!stop ? createFromPattern(newOpts, seed) : []));
};
完全将其放入:
const list = ['one', 'one', 'two', 'two', 'three', 'one']
const pattern = ['one', 'two', 'three']
const count = list => list.reduce((acc, cur) => ({...acc, [cur]: (acc[cur] || 0) + 1}), {});
const createFromPattern = (opts, seed) => {
const newOpts = {...opts};
const pick = seed.reduce((acc, cur) => [...acc, ...(newOpts[cur] ? newOpts[cur]-- && [cur] : [])], []);
const stop = Math.max(...Object.values(newOpts)) <= 0;
return [].concat(pick, (!stop ? createFromPattern(newOpts, seed) : []));
};
console.log(
createFromPattern(count(list), pattern)
);