最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

ecmascript 6 - Elegant array transformation in Javascript - Stack Overflow

programmeradmin0浏览0评论

What's an elegent way - purely functional, ideally - to transform (reduce?) this array:

var in = [
  { a: 1, b: 'x', c: 'foo' },
  { a: 1, b: 'y', c: 'goo' },
  { a: 2, b: 'x', c: 'hoo' },
  { a: 2, b: 'y', c: 'joo' }
]

Into this:

var out = [
  { a: 1, x: 'foo', y: 'goo' },
  { a: 2, x: 'hoo', y: 'joo' }
]

The logic is that all elements should be joined based on their a property, and all b and c properties denote key/value pairs respectively that should be merged into the single object based on their shared a value.

What's an elegent way - purely functional, ideally - to transform (reduce?) this array:

var in = [
  { a: 1, b: 'x', c: 'foo' },
  { a: 1, b: 'y', c: 'goo' },
  { a: 2, b: 'x', c: 'hoo' },
  { a: 2, b: 'y', c: 'joo' }
]

Into this:

var out = [
  { a: 1, x: 'foo', y: 'goo' },
  { a: 2, x: 'hoo', y: 'joo' }
]

The logic is that all elements should be joined based on their a property, and all b and c properties denote key/value pairs respectively that should be merged into the single object based on their shared a value.

Share Improve this question edited Feb 12, 2017 at 18:43 Yuval Adam asked Feb 12, 2017 at 18:38 Yuval AdamYuval Adam 165k95 gold badges317 silver badges404 bronze badges 3
  • you want the last element in the set of all elements with the same a value? – Ryan Commented Feb 12, 2017 at 18:40
  • What is logic to derive out? Note, in throws Uncaught SyntaxError: Unexpected token in – guest271314 Commented Feb 12, 2017 at 18:40
  • I described the logic in my question, sorry for not stating that upfront. – Yuval Adam Commented Feb 12, 2017 at 18:43
Add a ment  | 

5 Answers 5

Reset to default 8

You can use a hash object, and reduce to wrap the hashing like this:

const arr = [
  { a: 1, b: 'x', c: 'foo' },
  { a: 1, b: 'y', c: 'goo' },
  { a: 2, b: 'x', c: 'hoo' },
  { a: 2, b: 'y', c: 'joo' }
];

let result = Object.values(             // the result is the values of the hash object
  arr.reduce((hash, o) => {             // hash is a hash object that make it easier to group the result
    hash[o.a] = hash[o.a] || {a: o.a};  // if there is no object in the hash that have the value of the key a equal to o.a, then create a new one
    hash[o.a][o.b] = o.c;               // set the value of the key stored in o.b to o.c
    return hash;
  }, {})
);

console.log(result);

You could use a closure with a Map

var input = [{ a: 1, b: 'x', c: 'foo' }, { a: 1, b: 'y', c: 'goo' }, { a: 2, b: 'x', c: 'hoo' }, { a: 2, b: 'y', c: 'joo' }],
    output = input.reduce((map => (r, o) => (!map.has(o.a) && map.set(o.a, r[r.push({ a: o.a }) - 1]), map.get(o.a)[o.b] = o.c, r))(new Map), []);

console.log(output);
.as-console-wrapper { max-height: 100% !important; top: 0; }

You can use forEach and Object.assign to group by a and then map to return object values.

var data = [
  { a: 1, b: 'x', c: 'foo' },
  { a: 1, b: 'y', c: 'goo' },
  { a: 2, b: 'x', c: 'hoo' },
  { a: 2, b: 'y', c: 'joo' }
]

var r = {}
data.forEach(e => r[e.a] = Object.assign((r[e.a] || {}), {a: e.a, [e.b]: e.c}))
r = Object.keys(r).map(e => r[e])

console.log(r)

I like provided answers, but here is my attempt. I believe it's more readable, but it uses Object.assign and Object.values

const input = [
  { a: 1, b: 'x', c: 'foo' },
  { a: 1, b: 'y', c: 'goo' },
  { a: 2, b: 'x', c: 'hoo' },
  { a: 2, b: 'y', c: 'joo' }
]

const map = input.reduce((acc, obj) => {
  const [a, key, value] = Object.values(obj)
  const newObj = {a, [key]: value}

  if (acc[a]) {
    Object.assign(acc[a], newObj)
  } else {
   acc[a] = newObj
  }

  return acc 
}, {})

console.log(Object.values(map))

Not sure if approach is elegant or functional, though returns expected result using for..of loops, Array.prototype.some() and Object.assign()

function props(array, key, prop1, prop2) {
  let arr = [];
  for (let obj of array) {
    let o = {};
    for (let {[key]:_key, [prop1]:_prop1, [prop2]:_prop2} of [obj]) {
      o[_prop1] = _prop2;
      o[key] = _key;
    }
    if (!arr.some(p => p[key] === o[key])) arr.push(o);
    for (let prop of arr) {
      if (prop[key] == o[key]) {
        prop = Object.assign(prop, o)
      }
    }
  }
  return arr
}

var _in = [
  { a: 1, b: 'x', c: 'foo' },
  { a: 1, b: 'y', c: 'goo' },
  { a: 2, b: 'x', c: 'hoo' },
  { a: 2, b: 'y', c: 'joo' }
];

console.log(props(_in, "a", "b", "c"));

发布评论

评论列表(0)

  1. 暂无评论