I have an object
var myObject = {"audi": "gas", "tesla": "electric", "bmw": "electric", "mercedes": "electric"}
and I want to group all keys with same value in one string like using only es5
tesla bmw mercedes: electric. audi: gas
I used combination of Object.keys and Object.values but it didn't work for me
var res = ''
Object.keys(myObject).map(function(key) {
Object.values(myObject).map(function(val) {
if (myObject[key] === val) {
kes = {
[res.concat(key)]: val
}
}
})
})
It would make more sense to group by 'fuel'. For that, you can use a reducer.
In the snippet a few different roads to Rome ...
const logElem = document.querySelector(`pre`);
var myObject = {
audi: "gas",
tesla: "electric",
bmw: "electric",
mercedes: "electric"
};
const byFuel = Object.entries(myObject)
.reduce((acc, [key, value]) =>
({ ...acc, [value]: (acc[value] || []).concat(key) }), {});
logElem.textContent = `***By fuel (ES6)***\n ${
JSON.stringify(byFuel, null, 2)}`;
// to swap keys and values from [byFuel]
const byCars = Object.entries(byFuel)
.reduce((acc, [key, value]) => ({ ...acc,
[value.join(`,`)]: key
}), {});
logElem.textContent += `\n\n***By cars from byFuel (ES6)***\n${
JSON.stringify(byCars, null, 2)}`;
// Use one reducer (ES6)
const byCarsInOne = Object.entries(myObject)
.reduce((acc, [key, value]) => {
const keysAggregatedAsSingleKey = Object.keys(myObject)
.filter( key => myObject[key] === value )
.join(`,`);
return acc[keysAggregatedAsSingleKey]
? acc
: { ...acc, [keysAggregatedAsSingleKey]: value };
}, {});
logElem.textContent += `\n\n***One reducer***\n${
JSON.stringify(byCarsInOne, null, 2)}`;
// ES5 (really necessary? All modern browsers support es6)
var byFuelEs5 = {};
var byCarsEs5 = {};
for (var key in myObject) {
var ky = myObject[key];
byFuelEs5[ky] = ky in byFuelEs5
? byFuelEs5[ky].concat(key)
: [key];
}
logElem.textContent += `\n\n***ES5***\n${
JSON.stringify(byFuelEs5, null, 2)}`;
for (var key in byFuelEs5) {
byCarsEs5[byFuelEs5[key].join(`,`)] = key;
}
logElem.textContent += `\n\n${
JSON.stringify(byCarsEs5, null, 2)}`;
// Object.keys ES5, not very efficient
// (makes you *really* want to use ES6 ;)
var cars = Object.keys(myObject);
var byCarsEs5_2 = cars
.map( function(key) {return [myObject[key], key]; })
.map( function(kv) {
var fuel = kv[0];
var comma = this[fuel] ? "," : "";
this[fuel] = (this[fuel] || "") + comma + kv[1];
return this; }, {} )
.map( function(obj) {
var keys = Object.keys(obj)
.map( key => this[obj[key]] = key );
return this;
}, {}).shift();
logElem.textContent += `\n\n***Object.keys and map ES5***\n${
JSON.stringify(byCarsEs5_2, null, 2)}`;
// Finally, reduce from Object.keys my be more efficient
var byCarsEs5_3 = cars
.reduce( function(acc, car) {
var fuel = myObject[car];
if (!~acc.fuels.indexOf(fuel)) {
acc.fuels.push(fuel);
var carsByFuel = cars.filter(key => myObject[key] === fuel);
acc.result[carsByFuel] = fuel;
}
return acc;
}, {fuels: [], result: {}} ).result;
logElem.textContent += `\n\n***ES5 one reducer from Object.keys***\n${
JSON.stringify(byCarsEs5_3, null, 2)}`;
<pre></pre>
Would this work for you (IE compatible)?
var myObject = {
"audi": "gas",
"tesla": "electric",
"bmw": "electric",
"mercedes": "electric"
};
var reverseObject = Object.keys(myObject).reduce(function(result, car) {
var type = myObject[car], list = result[type];
if (!list) result[type] = list = [];
list.push(car);
return result;
}, {});
console.log(reverseObject);
var result = Object.keys(reverseObject).map(function(type) {
return reverseObject[type].join(" ") + ": " + type;
}).join(".");
console.log(result);
var myObject = {audi: "gas", "tesla": "electric", bmw: "electric", "mercedes": "electric"};
var helper = Object.entries(myObject).reduce((helperObj,item) => {
var key = item[0];
var val = item[1];
if(val in helperObj) {
helperObj[val].push(key)
} else {
helperObj[val] = [key];
}
return helperObj;
}, {});
var res = Object.entries(helper).reduce((theRes,item) => {
var fuel = item[0];
var cars = item[1];
var resKey = cars.join(' ');
theRes[resKey] = fuel;
return theRes;
}, {});
console.log(res)