From the comments I assume this data is possible:
var myData = [
{
action:{
remove_item: {
text: "delete",
textToDisplay: "Remove"
},
edit_item: {
text: "edit",
textToDisplay: "Edit"
}
}
},
{
action:{
remove_item: {
text: "delete",
textToDisplay: "Remove"
},
// note this _key_ is duplicated below (see note at the bottom)
add_item: {
text: "addy",
textToDisplay: "Addy"
}
}
},
{
action:{
add_item: {
text: "add",
textToDisplay: "Add"
}
}
}
];
A possible reducer could look like this:
myData.reduce(function(memo, obj, index) {
let key,
action = obj.action,
entries = Object.entries(action),
entry,
data,
keyIndex;
// action may have multiple fields (see note)
for (entry of entries) {
// the object field name is the key (see note)
// key = entry[0];
// the text attribute is the key (see note)
key = entry[1].text;
// index where in result[] the object is
// already stored (if so)
keyIndex = memo._keyIndex.indexOf(key);
if (keyIndex == -1) {
// key not indexed (and saved) yet
data = {};
Object.assign(data, entry[1], { count: 1 });
memo.result.push(data);
memo._keyIndex.push(key);
} else {
// key already indexed, get the data and
// increment counter
data = memo.result[keyIndex];
data.count++;
}
}
if (index < myData.length - 1) {
// for all items but last memo is an internal wrapper object
return memo;
} else {
// for final item return the actual result
return memo.result;
}
}, { result: [] /* actual result, this is finally returned */, _keyIndex: [] /* temp. index of keys */ });
To understand this code, you should be familar with:
- reduce() to transform an array to another data type entry by entry
- Object.entries() to get key-value pairs of an object in form of an array
- for..of loop to iterate array/object entries
The interesting part here is, that the "memo" object holds two references during the run. This allows tracking duplicate keys in _keyIndex
. Only with the last element, the result
array is returned from reduce()
.
Note:
- The for..of loop is used to process multiple fields inside the
{ action: { } }
object (from the comments on your question). If not required, processing entries[0]
with the code inside the for..of block suffices.
- The lines assigning
key
determine the key that is checked for duplicates.
- If the field name in
action
is the determining key, the first (commented) line would be enough. (This makes "Addy" appear in the results, counted twice.)
- If the value of the
text
field in an action object matters, the second line is required. (This makes "Addy" and "Add" appear in the results.)
Depending on the determining key, the resulting object may still have duplicates, but this code should direct you well enough.