使用函数式编程复制数组的元素

时间:2018-11-11 01:06:55

标签: javascript arrays object functional-programming

我正在尝试复制数组中的每个元素,但是使用功能样式。

我目前有这个:

["a", "b", "c"]

我得到这个:

["a","a","b","b","c","c"]

到目前为止,我已经尝试了以下操作,将每个元素映射到一个数组,然后使用flat()获得一个1d数组。有没有一种更清洁的方法,因为感觉就像我在滥用地图和公寓。

["a", "b", "c"].map(item => [item, item]).flat();

有更好的方法吗?


我试图提供一个尽可能简单的示例,但省略了一些细节。实际输入未排序,因为元素不可比。 就像这样:

[
  {
    a:"a"
    b:"b"
  },
  {
    c: 1
    d: 2
  },
  {
    apple: {},
    sellers: ["me", "her"]
  }
]

重复的结果应该是这样的,其中重复的元素彼此相邻:

[
  {
    a:"a"
    b:"b"
  },
  {
    a:"a"
    b:"b"
  },
  {
    c: 1
    d: 2
  },
  {
    c: 1
    d: 2
  },
  {
    apple: {},
    sellers: ["me", "her"]
  },
  {
    apple: {},
    sellers: ["me", "her"]
  }
]

5 个答案:

答案 0 :(得分:6)

Array.reduce在这里在语义上是合适的方法:取一个对象(在这种情况下为数组)并返回不同类型,长度或形状不同的对象(注意:已编辑以使用Array.push以提高@slider建议的性能):

编辑:我已经编辑了答案,以反映OP的更新的输入数据。另外请注意,该解决方案可以跨浏览器和NodeJS兼容,而无需进行编译。

let data = [
  {
    a:"a",
    b:"b",
  },
  {
    c: 1,
    d: 2
  },
  {
    apple: {},
    sellers: ["me", "her"]
  }
];

let result = data
  .reduce((acc, el) => {
    acc.push(el, el);
    return acc;
  }, []);
  
console.log(JSON.stringify(result, null, 2));

否则,您可以map的每个元素进行复制,然后将它们组合:

let data = [
  {
    a:"a",
    b:"b",
  },
  {
    c: 1,
    d: 2
  },
  {
    apple: {},
    sellers: ["me", "her"]
  }
];

let result = data.map(item => [item, item]).reduce((acc, arr) => acc.concat(arr));

console.log(JSON.stringify(result, null, 2));

如此处其他答案所述,这两种方法的优点都是不需要对原始数组进行排序。

答案 1 :(得分:4)

您可以使用函数reduce并在每次迭代中连接相同的对象。

let array = ["a", "b", "c"],
    result = array.reduce((a, c) => a.concat(c, c), []);
    
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

答案 2 :(得分:4)

我会推荐Array.prototype.flatMap

const twice = x =>
  [ x, x ]
  
console.log
  ( [ 'a', 'b', 'c' ] .flatMap (twice) // [ 'a', 'a', 'b', 'b', 'c', 'c' ]
  , [ 1, 2, 3, 4, 5 ] .flatMap (twice) // [ 1, 1, 2, 2, 3, 3, 4, 4, 5, 5 ]
  )

flatMap对于各种事物都很有用

const tree =
  [ 0, [ 1 ], [ 2, [ 3 ], [ 4, [ 5 ] ] ] ]
  
const all = ([ value, ...children ]) =>
  [ value ] .concat (children .flatMap (all))
  
console.log (all (tree))
// [ 0, 1, 2, 3, 4, 5 ]

真的很酷的东西

const ranks =
  [ 'J', 'Q', 'K', 'A' ]
  
const suits =
  [ '♡', '♢', '♤', '♧' ]

console.log
  ( ranks .flatMap (r =>
      suits .flatMap (s =>
        [ [ r, s ] ]
      )
    )
  )

// [ ['J','♡'], ['J','♢'], ['J','♤'], ['J','♧']
// , ['Q','♡'], ['Q','♢'], ['Q','♤'], ['Q','♧']
// , ['K','♡'], ['K','♢'], ['K','♤'], ['K','♧']
// , ['A','♡'], ['A','♢'], ['A','♤'], ['A','♧']
// ]

答案 3 :(得分:2)

您可以这样做:

var arr = ["a", "b", "c"];
arr = arr.concat(arr).sort();

这是完成您要执行的操作的最简单方法之一。

答案 4 :(得分:0)

最简单的解决方案是使用flatMap():

const source = ["a", "b", "c"];
const result = source.flatMap(item => [item, item]);
  

['a','a','b','b','c','c']

一些经典:

let source = ["a", "b", "c"];

const originalLength = source.length;
for(let i = 0; i <= originalLength + (originalLength - 2); i++) {
  source.splice(i, 0, source[i++]);
}
  

['a','a','b','b','c','c']