I have an object like:
Object {v: 1, b: 1, n: 1, m: 1, c: 2, d: 3}
I am trying to collect keys that has same values and generate an array (so in this case [v, b, n, m].
So if I know 1, how can I get v,b,n,m in an array?
You can use Object.keys() to get key values of the object, then filter values based on your condition using filter()
var obj = {
v: 1,
b: 1,
n: 1,
m: 1,
c: 2,
d: 3
},
val = 1;
var res = Object.keys(obj).filter(function(v) {
return obj[v] == val;
});
document.write('<pre>' + JSON.stringify(res, null, 4) + '</pre>');
Performance? Simple for...in loop.
var myObj = {v: 1, b: 1, n: 1, m: 1, c: 2, d: 3};
function collect (obj, value) {
var arr = [];
for (var key in obj)
if (obj.hasOwnProperty(key) && obj[key] === value)
arr.push(key);
return arr;
}
console.log(collect(myObj, 1));
Fancy? Object.keys, and Array.prototype.filter.
var myObj = {v: 1, b: 1, n: 1, m: 1, c: 2, d: 3};
function collect (obj, value) {
return Object.keys(obj).filter(key => obj[key] === value);
}
console.log(collect(myObj, 1));
using the underscore.js library you can do the following
var object = {v: 1, b: 1, n: 1, m: 1, c: 2, d: 3};
var output = _.map(object, function(value, key){
if(value == 1){
return key
}
}).filter(function(value){
return value;
});
console.log(output);
Related
let obj = { T: 1, h: 1, i: 3, s: 3, t: 1, r: 1, n: 1, g: 1 };
In the given object we have 2 keys(i & s both have same value 3) contains same value. I need to keep one key/value pair and another wants to remove.
How we can achieve this?
Make a copy and leave one field out?
let obj2 = { T: obj.T, h: obj.h, i: obj.i, t: obj.t, r: obj.r, n: obj.n, g: obj.g };
;-)
It's not super clear if you want to omit all keys with duplicate values or just some keys. In case you want the latter, here's a reusable function for that:
function copyWithout(source, ...keysToOmit) {
return Object.entries(source).reduce(
(accumulator, [key, value]) => {
return keysToOmit.includes(key)
? accumulator
: Object.assign(accumulator, { [key]: value });
},
Object.create(null) // or just {}
);
}
And use it like so:
copyWithout(obj, 'i');
Can be used to omit multiple keys as well:
copyWithout(obj, 'i', 't', 'r');
You can loop over object keys and add values in some temp array. Verify from that temp array and if value already exist in it then delete that key from object. Try like below.
let obj = { T: 1, h: 1, i: 3, s: 3, t: 1, r: 1, n: 1, g: 1 };
let val = [];
// loop over keys and verify that if value is repeating then delete that key from object.
Object.keys(obj).forEach(k => {
if (val.includes(obj[k])) {
delete obj[k];
} else {
val.push(obj[k])
}
});
console.log(obj);
Alternatively if you wish to keep your object as it is and want output in another object then try like below.
let obj = { T: 1, h: 1, i: 3, s: 3, t: 1, r: 1, n: 1, g: 1 };
let val = [];
let newObj = {};
// loop over keys and verify that if value is repeating then delete that key from object.
Object.keys(obj).forEach(k => {
if (!Object.values(newObj).includes(obj[k])) {
newObj[k] = obj[k];
}
});
console.log('newObj', newObj);
console.log('obj', obj);
You can use the following and swap key values twice,
let obj = { T: 1, h: 1, i: 3, s: 3, t: 1, r: 1, n: 1, g: 1 };
function swapKV(ob) {
return Object.entries(ob).reduce((p,[key,value]) => ({...p,[value]: key}),{})
}
swapKV(swapKV(obj))
You could save all unique values in set. This is the most optimal solution since it takes O(n) in time.
let obj = { T: 1, h: 1, i: 3, s: 3, t: 1, r: 1, n: 1, g: 1 };
function removeDuplicateValues(obj) {
const uniqueValues = new Set();
const uniquePairs = {};
Object.keys(obj).forEach(key => {
const curValue = obj[key];
if (!uniqueValues.has(curValue)) {
uniqueValues.add(curValue);
uniquePairs[key] = curValue;
}
});
return uniquePairs;
}
console.log(removeDuplicateValues(obj)) // {T: 1, i: 3}
const object = { a: 1, b: 2, c: 3, d: 2, e: 3 };
const removeUniqueValuesFromObject = (object) => {
const map = new Map();
// loop through all the attributes on an object
for (const [key, value] of Object.entries(object)) {
// check if the value already exists in map, if yes delete the attribute
if (map.has(value)) {
delete object[`${key}`];
continue;
}
// if value not found, add it to the map
map.set(value, key);
}
// return the updated object
return object;
};
const result = removeUniqueValuesFromObject(object);
console.log(result);
Here is the task
#param {object} ???
#returns {object} an object with the given object's values as keys, and keys as values. If there are duplicate values in the input object, only the first key-value pair should be used and subsequent pairs with the same value discarded.
2.Here is what i did code
What's wrong with it? How should i rework?
const object5 = { a: 1, b: 2, c: 3, d: 1 };
const object6 = { a: 1, b: 1, c: 1, d: 1 };
function swapPairs2(obj){
let newObject = {};
for(const key in obj){
let value = obj[key]
newObject[value] = key;
}
return newObject;
}
3.Here are the tests
test(swapPairs2(object5), { 1: "a", 2: "b", 3: "c" });
test(swapPairs2(object6), { 1: "a" });
4.Here is the error i got
I am supposed to get the first key-value pair, but a random return.
You can also reverse the entries.
const object5 = { a: 1, b: 2, c: 3, d: 1 };
const object6 = { a: 1, b: 1, c: 1, d: 1 };
const swapPairs2 = obj => Object.fromEntries(
Object.entries(obj)
.reverse() // Keep the first, not the last
.map(entry => [entry[1], entry[0]]) // Reverse the key and vlaue
);
console.log(swapPairs2(object5));
console.log(swapPairs2(object6));
Only add the value/key pairs, if the value doesn't already exist on newObject by checking with the in operator:
function swapPairs2(obj) {
const newObject = {};
for (const key in obj) {
const value = obj[key];
if(!(value in newObject)) {
newObject[value] = key;
}
}
return newObject;
}
const object5 = { a: 1, b: 2, c: 3, d: 1 };
const object6 = { a: 1, b: 1, c: 1, d: 1 };
console.log(swapPairs2(object5));
console.log(swapPairs2(object6));
Another option is to use Array.reduce():
const swapPairs2 = obj =>
Object.entries(obj)
.reduce((acc, [k, v]) =>
v in acc
? acc
: { ...acc, [v]: k }
, {})
const object5 = { a: 1, b: 2, c: 3, d: 1 };
const object6 = { a: 1, b: 1, c: 1, d: 1 };
console.log(swapPairs2(object5));
console.log(swapPairs2(object6));
You can do it by taking the object keys and using the Array.reduce() method on the keys.
const object5 = { a: 1, b: 2, c: 3, d: 1 };
const object6 = { a: 1, b: 1, c: 1, d: 1 };
const swapPairs2 = (obj) => Object.keys(obj)
.reduce((a, c) => (a[obj[c]] = a[obj[c]] ?? c, a), {});
console.log(swapPairs2(object5));
console.log(swapPairs2(object6));
Or using the Array.reduce() method on the Object.entries()
const object5 = { a: 1, b: 2, c: 3, d: 1 };
const object6 = { a: 1, b: 1, c: 1, d: 1 };
const swapPairs2 = obj => Object.entries(obj)
.reduce((acc, [key, val]) => (acc[val] = acc[val] ?? key, acc), {})
console.log(swapPairs2(object5));
console.log(swapPairs2(object6));
So I have an array of objects with some varying number of properties (but the property names are known), for example:
let data = [{a: 10, b: 1, c:10},
{a: 17, b: 2, c:16},
{a: 23, b: 3, c:41}]
I need to construct an object that sums up the values in the respective properties, so in this example I'd need to construct an object {a: 50, b: 6, c:67}
I wrote the following function to do this:
calcTotalForDataProps(data, props) {
let summedData = {}
for (const prop of props) {
summedData[prop] = 0;
}
data.forEach((dataObj) => {
for (const prop of props) {
summedData[prop] += dataObj[prop];
}
});
return summedData;
}
And you call it like this:
calcTotalForDataProps(data, ['a', 'b', 'c']);
But I'm wondering if there's a much shorter way to write this with ES6?
You could map the wanted props with their new sums for getting an object as result.
function calcTotalForDataProps(data, props) {
return data.reduce((r, o) => Object
.fromEntries(props.map(k => [k, (r[k] || 0) + o[k]])
), {});
}
const data = [{ a: 10, b: 1, c: 10}, { a: 17, b: 2, c: 16 }, { a: 23, b: 3, c: 41 }]
console.log(calcTotalForDataProps(data, ['a', 'b', 'c']));
There's no need to iterate over the properties initially - you can create the property inside the other loop if it doesn't exist yet.
let data = [{a: 10, b: 1, c:10},
{a: 17, b: 2, c:16},
{a: 23, b: 3, c:41}]
const calcTotalForDataProps = (data, props) => {
const summedData = {};
for (const obj of data) {
for (const [prop, num] of Object.entries(obj)) {
summedData[prop] = (summedData[prop] || 0) + num;
}
}
return summedData;
}
console.log(calcTotalForDataProps(data));
Implement the sumObjects function, which takes an unlimited number of objects and returns an object that combines all the objects entered.
Notes:
All object properties will have numeric values only
If the object keys match, the values of the corresponding keys are summed
The function always returns an object
The numbers in the object can be positive or negative
You can use the rest operator to collect arguments passed to a function in one array
Examples:
const obj = {};
sumObjects() === {}
sumObjects(obj) === {}
and
const first = {a: 2, b: 4};
const second = {a: 2, b: 10};
const third = {d: -5};
sumObjects(first) === {a: 2, b: 4}
sumObjects(first, third) === {a: 2, b: 4, d: -5}
sumObjects(first, second, third) === {a: 4, b: 14, d: -5}
This is my code.
function sumObjects(...params) {
let C = Object.fromEntries(
Object.keys(params[0])
.concat(Object.keys(params[1]))
.map(k => [k,
(params[0][k] || 0) + (params[1][k])
])
)
return C
}
I don't know how to add all these objects into one.
The bottom line is that I need to combine all the objects, but I just don't know how to do this, I can't find anything.
You can iterate over the param objects using .reduce and for each object, set/update its properties in acc:
function sumObjects(...params) {
return params.reduce((acc,item) => {
Object.entries(item).forEach(([property,value]) => {
const prev = acc[property];
acc[property] = prev ? prev+value : value;
});
return acc;
}, {});
}
const first = { a: 2, b: 4 };
const second = { a: 2, b: 10 };
const third = { d: -5 };
console.log( sumObjects(first) );
console.log( sumObjects(first, third) );
console.log( sumObjects(first, second, third) );
You could reduce the array of objects and iterate the entries of a single object.
const
sumObjects = (...objects) => objects.reduce((r, o) => {
Object.entries(o).forEach(([k, v]) => r[k] = (r[k] ||0) + v);
return r;
}, {}),
first = { a: 2, b: 4 },
second = { a: 2, b: 10 },
third = { d: -5 };
console.log(sumObjects(first)); // {a: 2, b: 4}
console.log(sumObjects(first, third)); // {a: 2, b: 4, d: -5}
console.log(sumObjects(first, second, third)); // {a: 4, b: 14, d: -5}
.as-console-wrapper { max-height: 100% !important; top: 0; }
Say I have an array of 3 objects like this:
[
{
a: 4,
b: 5,
c: 4
},
{
a: 3,
b: 5,
c: 6
},
{
a: 2,
b: 3,
c: 3
}
]
I would like to return an array of arrays containing the objects that share a common value for the property b. So the resulting array would contain only one array containing 2 objects like this:
[
[
{
a: 4,
b: 5,
c: 4
},
{
a: 3,
b: 5,
c: 6
}
]
]
How would I do this?
You could do this with map and filter
var data = [{"a":4,"b":5,"c":4},{"a":3,"b":5,"c":6},{"a":2,"b":3,"c":3}];
var check = data.map(e => {return e.b});
var result = [data.filter(e => { return check.indexOf(e.b) != check.lastIndexOf(e.b)})];
console.log(result)
To group multiple objects in separate arrays with same b values you can use map and forEach
var data = [{"a":4,"b":5,"c":4},{"a":3,"b":5,"c":6},{"a":2,"b":3,"c":3}, {"a":3,"b":7,"c":6},{"a":2,"b":7,"c":3}], result = [];
var check = data.map(e => {return e.b});
data.forEach(function(e) {
if(check.indexOf(e.b) != check.lastIndexOf(e.b) && !this[e.b]) {
this[e.b] = [];
result.push(this[e.b]);
}
(this[e.b] || []).push(e);
}, {});
console.log(result)
This proposal uses a single loop with Array#forEach but without Array#indexOf.
var array = [{ a: 4, b: 5, c: 4 }, { a: 3, b: 5, c: 6 }, { a: 2, b: 3, c: 3 }],
grouped = [];
array.forEach(function (a) {
this[a.b] = this[a.b] || [];
this[a.b].push(a);
this[a.b].length === 2 && grouped.push(this[a.b]);
}, Object.create(null));
console.log(grouped);
You can create a function that accepts fulfillment criteria and will return as many nested arrays as rules passed.
Let's say you have an array of objects, arr.
var arr = [{a: 1, b: 2}, {a: 3, b: 2}, {a: 3, b: 4}, {a: 1, b: 1}]
And you want to return an array with with nested arrays that fulfill a particular requirement, let's say you want objects with an a:1 and b:2.
You can create a function that loops through your rules and creates a nested array with the objects that fulfill each rule.
For example:
var arr = [{a: 1, b: 2}, {a: 3, b: 2}, {a: 3, b: 4}, {a: 1, b: 1}]
function makeNestedArrays() {
var rules = [].slice.call(arguments);
return rules.reduce(function(acc, fn) {
var nestedArr = [];
arr.forEach(function(obj) {
if (fn(obj)) {
nestedArr.push(obj);
}
});
// only push nested array
// if there are matches
if (nestedArr.length) {
acc.push(nestedArr);
}
return acc;
}, []);
}
var result = makeNestedArrays(
function(obj) { return obj.a === 1; },
function(obj) { return obj.b === 2; }
);
console.log(result);
This allows you to pass as many "rules" as you want, and will create a nested array for each rule so long as there is at least one match.
You could use a Map to group them, this should work with any kind of value (just be sure the equality rules check out):
var arr = [{
a: 4,
b: 5,
c: 4
}, {
a: 3,
b: 5,
c: 6
}, {
a: 2,
b: 3,
c: 3
}];
var result = arr.reduce(function(m, o){
var value = o.b;
if(m.has(value)){
m.get(value).push(o);
} else {
m.set(value, [o]);
}
return m;
}, new Map());
console.log(...(result.values()));
If you'd need to filter out the groups of 1:
var arr = [{
a: 4,
b: 5,
c: 4
}, {
a: 3,
b: 5,
c: 6
}, {
a: 2,
b: 3,
c: 3
}];
var result = arr.reduce(function(m, o){
var value = o.b;
if(m.has(value)){
m.get(value).push(o);
} else {
m.set(value, [o]);
}
return m;
}, new Map());
result = [...result.values()].filter(a => a.length > 1);
console.log(result);