简体   繁体   中英

Array of objects to accumulate all object properties for which another property is the same

Let's say my array of objects looks like:

array1 = [
    { 
         rule: {
             column: "colName",
             value: "val1"
         }
    },
    { 
         rule: {
             column: "colName",
             value: "val2"
         }
    },
    { 
         rule: {
             column: "colName",
             value: "val3"
         }
    },
    { 
         rule: {
             column: "colName2",
             value: "val4"
         }
    }
]

I want to write something like a reduce operation that checks if rule.column are equal for all array elements and if so, to push into the values of one of them while removing the others. To give me something like:

array2 = [
    { 
         rule: {
             column: "colName",
             value: ["val1", "val2", "val3"]
         }
    },
    { 
         rule: {
             column: "colName2",
             value: ["val4"]
         }
    }
]

Is there a straightforward way to do this? I can definitely write a regular function to do this, but I am assuming I should be able to do a reduce operation on array1 instead?

Edit : the original question had otherProperty: {} properties after rule but my object doesn't actually have that (it's on the upper-level object)

Sure, just create an object with keys matching each column, push to the internal values array, and then grab the object's values:

 const input = [{ rule: { column: "colName", value: 'v1' }, otherProperty: 'otherProp', }, { rule: { column: "colName", value: 'v2' }, otherProperty: 'otherProp', }, { rule: { column: "colName", value: 'val3', }, otherProperty: 'otherProp', }, { rule: { column: "colName2", value: 'val4' }, otherProperty: 'otherProp', } ]; const outputCols = input.reduce((outputCols, { rule: { column, value }, ...otherProps}) => { if (!outputCols[column]) { outputCols[column] = { rule: { column, value: [] }, ...otherProps }; } outputCols[column].rule.value.push(value); return outputCols; }, {}); console.log(Object.values(outputCols)); 

Note that if the otherProps are different in subsequent objects, they'll be ignored currently.

You can use the function reduce to group and then get the values as an array.

The name otherProperty is out of scope, but you can use either the function Object.assign or the Spread syntax.

 let array1 = [ { rule: { column: "colName", value: ["val1"] }, otherProperty: {} }, { rule: { column: "colName", value: ["val2"] }, otherProperty: {} }, { rule: { column: "colName", value: ["val3"] }, otherProperty: {} }, { rule: { column: "colName2", value: ["val4"] }, otherProperty: {} }], result = Object.values(array1.reduce((a, c) => { (a[c.rule.column] || (a[c.rule.column] = {rule: {column: c.rule.column, value: []}, otherProperty: {}})).rule.value.push(...c.rule.value); return a; }, {})); console.log(result); 
 .as-console-wrapper { max-height: 100% !important; top: 0; } 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM