同一级别的对象组数组

时间:2019-12-21 11:39:59

标签: javascript lodash

我有一个具有不同批准者级别的数组。我需要组合相似级别的对象,并将它们与Name + counter分组。

"APPROVERS": [
        {
            "LEVEL": "L5",
            "EMAIL": "FTEST@TEST.COM",
            "FULLNAME": "FNAME",
            "POSITION": "FPOS",
            "SLA": "48",
            "STATUS": "INITIAL"
        },
        {
            "LEVEL": "L4",
            "EMAIL": "JTEST@TEST.COM",
            "FULLNAME": "JNAME",
            "POSITION": "JPOS",
            "SLA": "48",
            "STATUS": "INITIAL"
        },
        {
            "LEVEL": "L5",
            "EMAIL": "LTEST@TEST.COM",
            "FULLNAME": "LNAME",
            "POSITION": "GPOS",
            "SLA": "48",
            "STATUS": "INITIAL"
        },
        {
            "LEVEL": "L5",
            "EMAIL": "TTEST@TEST.COM",
            "FULLNAME": "TNAME",
            "POSITION": "CPOS",
            "SLA": "48",
            "STATUS": "INITIAL"
        }  
    ]

我需要将同一级别的对象合并为一个,并提供唯一的名称。

 "APPROVERS": [
        {
            "LEVEL": "L5",
            "EMAIL1": "FTEST@TEST.COM",
            "FULLNAME1": "FNAME",
            "POSITION1": "FPOS",
            "SLA1": "48",
            "STATUS1": "INITIAL",
            "EMAIL2": "LTEST@TEST.COM",
            "FULLNAME2": "LNAME",
            "POSITION2": "GPOS",
            "SLA2": "48",
            "STATUS2": "INITIAL",
            "EMAIL3": "TTEST@TEST.COM",
            "FULLNAME3": "TNAME",
            "POSITION3": "CPOS",
            "SLA3": "48",
            "STATUS3": "INITIAL"
        },
        {
            "LEVEL": "L4",
            "EMAIL": "JTEST@TEST.COM",
            "FULLNAME": "JNAME",
            "POSITION": "JPOS",
            "SLA": "48",
            "STATUS": "INITIAL"
        } 
    ]

我只尝试通过循环数组来组合EMAIL,但无法达到结果。建议。

var result = [];
    var i=0
    APPROVERS.forEach(function(obj) {
      var id = obj.LEVEL
      if(!this[id]) result.push(this[id] = obj);
      else this[id].EMAIL += obj.EMAIL+i;
      i++;
    }, Object.create(null));

    console.log(result)

5 个答案:

答案 0 :(得分:3)

您可以通过将对象中同一级别的元素进行分组来将级别与一系列元素相关联,例如:

{
  "L5": [
    {
      "EMAIL": "FTEST@TEST.COM",
      "FULLNAME": "FNAME",
      "POSITION": "FPOS",
      "SLA": "48",
      "STATUS": "INITIAL"
    },
    ...
  ],
  "L4": [
    {
      "EMAIL": "JTEST@TEST.COM",
      "FULLNAME": "JNAME",
      "POSITION": "JPOS",
      "SLA": "48",
      "STATUS": "INITIAL"
    }
  ]
}

然后遍历各个级别,并创建一个包含唯一级别的数组,这些级别通过每个元素的唯一键EMAIL{i}FULLNAME{i}POSITION{i}SLA{i}和{ {1}}:

STATUS{i}

这是完整的代码:

[
  {
    "LEVEL": "L5",
    "EMAIL1": "FTEST@TEST.COM",
    "FULLNAME1": "FNAME",
    "POSITION1": "FPOS",
    "SLA1": "48",
    "STATUS1": "INITIAL",
    ...
  },
  {
    "LEVEL": "L4",
    "EMAIL1": "JTEST@TEST.COM",
    "FULLNAME1": "JNAME",
    "POSITION1": "JPOS",
    "SLA1": "48",
    "STATUS1": "INITIAL"
  }
]
// prepare an intermediate representation of your data { level => approver[] }
const grouped = data['APPROVERS'].reduce((approvers, approver) => {
  const { LEVEL, ...props } = approver;
  approvers[LEVEL] = approvers[LEVEL] ? approvers[LEVEL].concat([props]) : [props]
  return approvers;
}, {})

// helper function to append a suffix to all keys of a given object
const suffixKeys = (obj, suffix) => {
  return Object.entries(obj).reduce((result, [key, value]) => {
    return { ...result, [key+suffix]: value } 
  }, {});
}

// combine the objects into an array using the intermediate representation
const result = Object.entries(grouped).map(([name, group]) => {
  return group.reduce((grouped, current, i) => {
    return { ...grouped, ...suffixKeys(current, i+1) }
  }, { LEVEL: name });
});

console.log(result)

但是,我认为中间格式更容易使用。

答案 1 :(得分:3)

通过放置标签lodash,我想您不介意使用它。我不确定您是否理解它,但我已尽力在简洁性和可读性之间取得平衡

function groupByLevel(approvers) {

  const group = _.groupBy(approvers, 'LEVEL');
  // console.log(group); // try logging to see what we have

  return Object.entries(group).map( ([LEVEL, array]) => {

    return array.reduce((acc, cur, idx) => ({
      ...acc,
      ['EMAIL'    + (idx + 1)]: cur.EMAIL    ,
      ['FULLNAME' + (idx + 1)]: cur.FULLNAME ,
      ['POSITION' + (idx + 1)]: cur.POSITION ,
      ['SLA'      + (idx + 1)]: cur.SLA      ,
      ['STATUS'   + (idx + 1)]: cur.STATUS   ,

    }), { LEVEL });
  })
}












var APPROVERS = [
  {
    LEVEL: 'L5',
    EMAIL: 'FTEST@TEST.COM',
    FULLNAME: 'FNAME',
    POSITION: 'FPOS',
    SLA: '48',
    STATUS: 'INITIAL'
  },
  {
    LEVEL: 'L4',
    EMAIL: 'JTEST@TEST.COM',
    FULLNAME: 'JNAME',
    POSITION: 'JPOS',
    SLA: '48',
    STATUS: 'INITIAL'
  },
  {
    LEVEL: 'L5',
    EMAIL: 'LTEST@TEST.COM',
    FULLNAME: 'LNAME',
    POSITION: 'GPOS',
    SLA: '48',
    STATUS: 'INITIAL'
  },
  {
    LEVEL: 'L5',
    EMAIL: 'TTEST@TEST.COM',
    FULLNAME: 'TNAME',
    POSITION: 'CPOS',
    SLA: '48',
    STATUS: 'INITIAL'
  }
]
console.log(groupByLevel(APPROVERS))
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.js"></script>

答案 2 :(得分:2)

以下算法完全可以实现您想要的:

let APPROVERS = [
  {
      "LEVEL": "L5",
      "EMAIL": "FTEST@TEST.COM",
      "FULLNAME": "FNAME",
      "POSITION": "FPOS",
      "SLA": "48",
      "STATUS": "INITIAL"
  },
  {
      "LEVEL": "L4",
      "EMAIL": "JTEST@TEST.COM",
      "FULLNAME": "JNAME",
      "POSITION": "JPOS",
      "SLA": "48",
      "STATUS": "INITIAL"
  },
  {
      "LEVEL": "L5",
      "EMAIL": "LTEST@TEST.COM",
      "FULLNAME": "LNAME",
      "POSITION": "GPOS",
      "SLA": "48",
      "STATUS": "INITIAL"
  },
  {
      "LEVEL": "L5",
      "EMAIL": "TTEST@TEST.COM",
      "FULLNAME": "TNAME",
      "POSITION": "CPOS",
      "SLA": "48",
      "STATUS": "INITIAL"
  }  
];

var result = {};
var compareLevel = {};

for (let index = 0; index < APPROVERS.length; index++) {
  if(Object.keys(compareLevel).includes(APPROVERS[index].LEVEL)){

    for (const key in APPROVERS[index]) {
      if(key == 'LEVEL') continue;
      let keyIndex = compareLevel[APPROVERS[index].LEVEL] + 1;
      result[APPROVERS[index].LEVEL][key + keyIndex] = APPROVERS[index][key];
    }
    
    compareLevel[APPROVERS[index].LEVEL]++;
  }else{
    result[APPROVERS[index].LEVEL] = APPROVERS[index];
    compareLevel[APPROVERS[index].LEVEL] = 1;
  }
}

let resultArr = Object.values(result);
console.log(Object.values(result));

答案 3 :(得分:2)

我看到这里有很多很好的答案(我会投票赞成),但是正如我所答应的,我向您传达了如何解决您的问题。让我显示代码

var theApprovers =  [
    {
        "LEVEL": "L5",
        "EMAIL": "FTEST@TEST.COM",
        "FULLNAME": "FNAME",
        "POSITION": "FPOS",
        "SLA": "48",
        "STATUS": "INITIAL"
    },
    {
        "LEVEL": "L4",
        "EMAIL": "JTEST@TEST.COM",
        "FULLNAME": "JNAME",
        "POSITION": "JPOS",
        "SLA": "48",
        "STATUS": "INITIAL"
    },
    {
        "LEVEL": "L5",
        "EMAIL": "LTEST@TEST.COM",
        "FULLNAME": "LNAME",
        "POSITION": "GPOS",
        "SLA": "48",
        "STATUS": "INITIAL"
    },
    {
        "LEVEL": "L5",
        "EMAIL": "TTEST@TEST.COM",
        "FULLNAME": "TNAME",
        "POSITION": "CPOS",
        "SLA": "48",
        "STATUS": "INITIAL"
    }  
]

function groupBy (collection, key) { // based on https://stackoverflow.com/a/34890276/903998
  return collection.reduce(function(grouped, element) {
    (grouped[element[key]] = grouped[element[key]] || []).push(element);
    return grouped;
  }, {});
};

function arrangeApprovers(approvers) {
  // first group by level
  var groupedByLevel = groupBy(approvers,"LEVEL")
  // then for each level do the arrange as you need
  var arrayOflevelWithApprovers = Object.keys(groupedByLevel).map(function(level) {
    var approversOfSameLevel = groupedByLevel[level]
    var levelWithApprovers = {"LEVEL" : level}
    approversOfSameLevel.forEach(function(approber, index) {
      var suffixNumber = index+1
      levelWithApprovers["EMAIL"+suffixNumber] = approber["EMAIL"]
      levelWithApprovers["FULLNAME"+suffixNumber] = approber["FULLNAME"]
      levelWithApprovers["POSITION"+suffixNumber] = approber["POSITION"]
      levelWithApprovers["SLA"+suffixNumber] = approber["SLA"]
      levelWithApprovers["STATUS"+suffixNumber] = approber["STATUS"]
    })
    return levelWithApprovers
  });
  return arrayOflevelWithApprovers;
}

var theApproversArrenged = arrangeApprovers(theApprovers) // so they are arrangen in the convenient fashion..
console.log(theApproversArrenged)

https://repl.it/repls/TruthfulLivelyInterface

您会发现theAprroversArrenged内部的元素以所需的方式排列。

免责声明,请注意,对于level4(以及具有唯一批准者的那些级别),生成的记录将引用其后缀为1的属性。希望不要成为让您感到烦恼的东西目的。

答案 4 :(得分:1)

LEVEL对数组进行分组后,可以映射组。检查组的长度。如果它只有一个项目,则可以退回该项目。如果大于1,则需要映射项目,并映射项目的键以包括项目的索引+ 1,然后将所有项目合并到单个对象中:

const fn = (arr, groupKey) => {
  const groups = _.groupBy(arr, groupKey);
  
  return _.map(groups, group =>
    group.length > 1 ? // if there's more than one item
      _.merge(... // merge all items
        _.map(group, (item, idx) => _.mapKeys( // map the items in the group
          item, (v, k) => k === groupKey ? k : `${k}${idx + 1}` // add the index to all keys, but LEVEL
        ))
      )
    :
    group[0]
  )
};

const data = {APPROVERS:[{LEVEL:"L5",EMAIL:"FTEST@TEST.COM",FULLNAME:"FNAME",POSITION:"FPOS",SLA:"48",STATUS:"INITIAL"},{LEVEL:"L4",EMAIL:"JTEST@TEST.COM",FULLNAME:"JNAME",POSITION:"JPOS",SLA:"48",STATUS:"INITIAL"},{LEVEL:"L5",EMAIL:"LTEST@TEST.COM",FULLNAME:"LNAME",POSITION:"GPOS",SLA:"48",STATUS:"INITIAL"},{LEVEL:"L5",EMAIL:"TTEST@TEST.COM",FULLNAME:"TNAME",POSITION:"CPOS",SLA:"48",STATUS:"INITIAL"}]};

const result = fn(data.APPROVERS, 'LEVEL')

console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.js"></script>