首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >按排序规则将数组减少为on数组

按排序规则将数组减少为on数组
EN

Stack Overflow用户
提问于 2019-02-20 22:58:55
回答 9查看 1.7K关注 0票数 23

我试图使用reduce()以“排序”顺序组合一组数组,以便具有类似索引的项在一起。例如:

代码语言:javascript
运行
复制
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'...的结果与上面的一样好。如果可能的话,我只想使用不变的变量。

我有一种方法:

代码语言:javascript
运行
复制
    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那样的变异循环。

EN

回答 9

Stack Overflow用户

发布于 2019-02-20 23:06:18

使用Array.from()创建一个长度为最长子数组的新数组。若要获取最长子数组的长度,请使用Array.map()获取长度数组,并取最大项。

Array.from()的回调中,使用Array.reduceRight()Array.reduce() (取决于您想要的顺序)从每个子数组收集项。如果子数组中存在当前索引,则接受该项。用Array.flat()将子数组压平。

代码语言:javascript
运行
复制
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);

票数 8
EN

Stack Overflow用户

发布于 2019-02-21 04:02:25

我用递归的方法来避免变异。

代码语言:javascript
运行
复制
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))

票数 7
EN

Stack Overflow用户

发布于 2019-02-21 05:05:14

下面是一个符合您指定的优雅标准的递归解决方案:

代码语言:javascript
运行
复制
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代码:

代码语言:javascript
运行
复制
collate :: [[a]] -> [a]
collate []  = []
collate xss = let yss = filter (not . null) xss
              in map head yss ++ collate (map tail yss)

前面的解决方案使用大踏步来计算答案。下面是一个递归解决方案,使用小步来计算答案:

代码语言:javascript
运行
复制
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代码:

代码语言:javascript
运行
复制
collate :: [[a]] -> [a]
collate []           = []
collate ([]:xss)     = collate xss
collate ((x:xs):xss) = x : collate (xss ++ [xs])

希望这能有所帮助。

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54796607

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档