将对象数组转换为新的数组结构

时间:2019-02-12 13:51:00

标签: javascript arrays reactjs lodash

道歉,但是我正在学习数组操作,尝试了一些我以前做过的类似的事情,但是无法弄清楚。我正在构建一个React应用程序,并且已经从UI中获取了我的数据,但是需要重新格式化API。我的有效载荷看起来像这样...

0: {from: "U20", Id: "1922", to: "U21"}
1: {from: "U20", Id: "9338", to: "U21"}
2: {from: "U20", Id: "1927", to: "U21"}
3: {from: "U20", Id: "1730", to: "U21"}

我需要为所有ids创建一个组,然后回发fromto字段。

{
    "from": "U20",
    "Ids": ["1922","9338","1927","1730"],
    "to:": "U21"
}

我有lodash作为帮助程序库。

10 个答案:

答案 0 :(得分:3)

要基于2个键进行分组,您可以使用reduce执行类似的操作。用新的密钥创建一个累加器对象,该密钥是fromto

的组合

const input = [
    { from: "U20", Id: "1922", to: "U21" },
    { from: "U20", Id: "9338", to: "U21" },
    { from: "U20", Id: "1927", to: "U21" },
    { from: "U20", Id: "1730", to: "U21" }
];

const merged = input.reduce((acc, { from, to, Id }) => {
    const key = `${from}-${to}`;
    acc[key] = acc[key] || { from, to, Ids:[] };
    acc[key]["Ids"].push(Id);
    return acc;
}, {})

const output = Object.values(merged);
console.log(output);

在您的情况下,如果您只想要第一个对象,则output[0]

答案 1 :(得分:1)

如果fromto字段中可能存在不同的值,则您的API需要进行更改以接受值的数组而不是一个字符串。但是,假设fromto的值在数组中的每个项目之间始终是相同的...

const payload = [
  {from: "U20", Id: "9338", to: "U21"},
  {from: "U20", Id: "1927", to: "U21"},
  {from: "U20", Id: "1730", to: "U21"},
];

const newValue = {
  from: payload[0].from,
  to: payload[0].to,
  Ids: payload.map(item => item.Id)
};

答案 2 :(得分:1)

const a = [
  {from: "U20", Id: "1922", to: "U21"},
  {from: "U20", Id: "9338", to: "U21"},
  {from: "U20", Id: "1927", to: "U21"},
  {from: "U20", Id: "1730", to: "U21"},
  {from: "U21", Id: "1745", to: "U22"},
  {from: "U21", Id: "1755", to: "U22"},
]

const f = array => {
  const result = []
  // key-value storage
  const variations = {}
  array.forEach(item => {
    // set storage key
    const key = `${item.from}-${item.to}`;
    // check if key exists
    // if exists use it, if not - create empty array
    variations[key] = variations[key] || []
    // push item ids to storage
    variations[key].push(item.Id)
  })
  Object.keys(variations).map(variation => {
    // deconstruct storage key back to "from" and "to" values
    const [from, to] = variation.split('-');
    const obj = {};
    // write "from" and "to" values
    obj.from = from;
    obj.to = to;
    // add stored values
    obj.ids = variations[variation]
    // save
    result.push(obj)
  })
  console.log(result)
}

f(a)

答案 3 :(得分:1)

通过以下操作,您可以记录每个Ids-> from键对的to的每个列表。

const entries = [
	{ from: 'U20', to: 'U21', Id: '1922' },
	{ from: 'U20', to: 'U21', Id: '9338' },
	{ from: 'U20', to: 'U21', Id: '1927' },
	{ from: 'U20', to: 'U21', Id: '1730' },
]

const output = entries.reduce((map, {from, to, Id}) =>
{
	if (!map[from])
	{
		map[from] = {}
	}
	
	if (!map[from][to])
	{
		map[from][to] = {from, to, Ids: []}
	}
	
	map[from][to].Ids.push(Id)
	
	return map
}, {})

console.log(output)

答案 4 :(得分:0)

使用数组reduce并在累加器中传递一个空对象。使用hasOwnProperty检查对象是否具有属性from,并且其值是否匹配,然后在id数组中推送值

let data = [{
    from: "U20",
    Id: "1922",
    to: "U21"
  },
  {
    from: "U20",
    Id: "9338",
    to: "U21"
  },
  {
    from: "U20",
    Id: "1927",
    to: "U21"
  },
  {
    from: "U20",
    Id: "1730",
    to: "U21"
  }
]


let newData = data.reduce(function(acc, curr) {
  if (acc.hasOwnProperty('from') && acc.from === curr.from) {
    acc.id.push(curr.Id)
  } else {
    acc = {
      from: curr.from,
      id: [curr.Id],
      to: curr.to
    }

  }
  return acc;
}, {});

console.log(newData)

答案 5 :(得分:0)

尝试一下

var idArray = [];
var newObj = {};
 var objArray = [{
    "from": "U20",
    "Id": "1922",
    "to": "U21"
},
{
    "from": "U20",
    "Id": "9338",
    "to": "U21"
},
{
    "from": "U20",
    "Id": "1927",
    "to": "U21"
},
{
    "from": "U20",
    "Id": "1730",
    "to": "U21"
}
]

      for(var i=0; i<objArray.length; i++) {
    for(var key in objArray[i]) {
      if(key == 'Id') idArray.push(objArray[i][key])
    }
  }
  newObj.from = objArray[0].from;
  newObj.to = objArray[0].to;
  newObj.Id = idArray;
  console.log(JSON.stringify(newObj));

答案 6 :(得分:0)

通过使用Map和用于两个值的分组的联接键来实现。

var data = [{ from: "U20", Id: "1922", to: "U21" }, { from: "U20", Id: "9338", to: "U21" }, { from: "U20", Id: "1927", to: "U21" }, { from: "U20", Id: "1730", to: "U21" }, { from: "U20", Id: "1730", to: "U22" }, { from: "U21", Id: "1730", to: "U22" }],
    result = Array.from(data
        .reduce(
             (m, { from, to, Id }) =>
                 (k => m.set(k, { from, to, Ids: [...(m.has(k) ? m.get(k).Ids : []), Id] }))
                 ([from, to].join('|')),
             new Map
        )
        .values()
    );

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

答案 7 :(得分:0)

还有一个决定:

const compare = (o1, o2) => o1.from === o2.from && o1.to === o2.to
return entries
    .reduce((arr,entry) => !arr.find(a=>compare(a,entry)) ? arr.concat(entry) : arr, [])
    .map( ({from,to})=> ({
        from,
        to,
        ids: entries.filter(i=>compare(i,{from,to})).map(({id})=>id)
        }))

答案 8 :(得分:0)

此解决方案使用lodash/fp通过fromto道具的组合来对数组中的所有对象进行分组。然后,通过合并每个组中的所有对象,它将所有组映射回数组。如果合并的props为Id,则将值合并为数组。

const { flow, groupBy, props, join, map, mergeAllWith, cond, nthArg, eq, concat } = _;

const fn = flow(
  groupBy(flow(                // group by joining from and to as the key
    props(['from', 'to']),
    join('-')
  )),
  map(mergeAllWith(cond([[     // merge all objects in each group
    flow(nthArg(2), eq('Id')), // if the prop name is Id, concat the values
    concat
  ]])))
);

const input = [
    { from: "U20", Id: "1922", to: "U21" },
    { from: "U20", Id: "9338", to: "U21" },
    { from: "U20", Id: "1927", to: "U21" },
    { from: "U20", Id: "1730", to: "U21" }
];

const result = fn(input);

console.log(result);
<script src='https://cdn.jsdelivr.net/g/lodash@4(lodash.min.js+lodash.fp.min.js)'></script>

答案 9 :(得分:0)

很简单。你可以做到

const arr = [
     {from: "U20", Id: "1922", to: "U21"},
     {from: "U20", Id: "9338", to: "U21"},
     {from: "U20", Id: "1927", to: "U21"},
     {from: "U20", Id: "1730", to: "U21"}]

const newObject = {
    from: arr[0].from,
    Ids: arr.map(record => (record.Id)),
    to: arr[0].to
    }