我试图使用reduce()
以“排序”顺序组合一组数组,以便具有类似索引的项在一起。例如:
input = [["one","two","three"],["uno","dos"],["1","2","3","4"],["first","second","third"]]
output = [ 'first','1','uno','one','second','2','dos','two','third','3','three','4' ]
只要它们在一起,具有相似索引的项目的排序就不重要了,所以'one','uno','1'...
的结果与上面的一样好。如果可能的话,我只想使用不变的变量。
我有一种方法:
const output = input.reduce((accumulator, currentArray, arrayIndex)=>{
currentArray.forEach((item,itemIndex)=>{
const newIndex = itemIndex*(arrayIndex+1);
accumulator.splice(newIndex<accumulator.length?newIndex:accumulator.length,0,item);
})
return accumulator;
})
但是它不是很漂亮,我不喜欢它,特别是因为它在forEach方法中变异累加器的方式。我觉得一定有一个更优雅的方法。
我不敢相信以前没有人问过这个问题,但我尝试过很多不同的查询,但都找不到,所以请告诉我它是否在那里,我错过了。有更好的办法吗?
为了澄清注释中的每个问题,我希望能够做到这一点,而不必像对待accumulator.splice
那样对任何变量或数组进行变异,并且只使用诸如.map
或.reduce
之类的函数方法,而不是像.forEach
那样的变异循环。
发布于 2019-02-20 23:06:18
使用Array.from()
创建一个长度为最长子数组的新数组。若要获取最长子数组的长度,请使用Array.map()
获取长度数组,并取最大项。
在Array.from()
的回调中,使用Array.reduceRight()
或Array.reduce()
(取决于您想要的顺序)从每个子数组收集项。如果子数组中存在当前索引,则接受该项。用Array.flat()
将子数组压平。
const input = [["one","two","three"],["uno","dos"],["1","2","3","4"],["first","second","third"]]
const result = Array.from(
{ length: Math.max(...input.map(o => o.length)) },
(_, i) => input.reduceRight((r, o) =>
i < o.length ? [...r, o[i]] : r
, [])
)
.flat();
console.log(result);
发布于 2019-02-21 04:02:25
我用递归的方法来避免变异。
let input = [["one","two","three"],["uno","dos"],["1","2","3","4"],["first","second","third"]]
function recursion(input, idx = 0) {
let tmp = input.map(elm => elm[idx])
.filter(e => e !== undefined)
return tmp[0] ? tmp.concat(recursion(input, idx + 1)) : []
}
console.log(recursion(input))
发布于 2019-02-21 05:05:14
下面是一个符合您指定的优雅标准的递归解决方案:
const head = xs => xs[0];
const tail = xs => xs.slice(1);
const notNull = xs => xs.length > 0;
console.log(collate([ ["one", "two", "three"]
, ["uno", "dos"]
, ["1", "2", "3", "4"]
, ["first", "second", "third"]
]));
function collate(xss) {
if (xss.length === 0) return [];
const yss = xss.filter(notNull);
return yss.map(head).concat(collate(yss.map(tail)));
}
它可以直接翻译成Haskell代码:
collate :: [[a]] -> [a]
collate [] = []
collate xss = let yss = filter (not . null) xss
in map head yss ++ collate (map tail yss)
前面的解决方案使用大踏步来计算答案。下面是一个递归解决方案,使用小步来计算答案:
console.log(collate([ ["one", "two", "three"]
, ["uno", "dos"]
, ["1", "2", "3", "4"]
, ["first", "second", "third"]
]));
function collate(xss_) {
if (xss_.length === 0) return [];
const [xs_, ...xss] = xss_;
if (xs_.length === 0) return collate(xss);
const [x, ...xs] = xs_;
return [x, ...collate(xss.concat([xs]))];
}
下面是等价的Haskell代码:
collate :: [[a]] -> [a]
collate [] = []
collate ([]:xss) = collate xss
collate ((x:xs):xss) = x : collate (xss ++ [xs])
希望这能有所帮助。
https://stackoverflow.com/questions/54796607
复制相似问题