How to combine array that has the same values in Javascript - javascript

I have the following array:
0: {x: "/", y: 8}
1: {x: "/a", y: 7}
2: {x: "/a", y: 2}
3: {x: "/", y: 1}
How can I turn that into:
0: {x: "/", y: 9}
1: {x: "/a", y: 9}
Where the same values of X have their Y value added on.
It should only look for the same values of X, if they are the same it combines them and adds their Y together.

You can use Array#reduce with an object to store the values for each x.
let arr = [{x: "/", y: 8},{x: "/a", y: 7},{x: "/a", y: 2},{x: "/", y: 1}];
let res = Object.values(arr.reduce((acc,{x,y})=>{
(acc[x] = acc[x] || {x, y:0}).y += y;
return acc;
}, {}));
console.log(res);

Related

Replace value of nested object with variable structure

I've an object like this:
const obj = {a: {x: 0, y: 0}}
that could be also:
const obj = {a: {x: 0, y: 0}, b: {x: 10, y: 3}, abcd: {x: -1, y: 0}}
So, the obj can have more than one key and with variables key names.
I need to replace each x value with a a string like this ${x}% so the x value + the percentage symbol.
How can I do that?
The expected results should be:
const obj = {a: {x: 0, y: 0}} // {a: {x: '0%', y: 0}}
const obj = {a: {x: 0, y: 0}, b: {x: 10, y: 3}, abcd: {x: -1, y: 0}} // {a: {x: '0%', y: 0}, b: {x: '10%', y: 3}, abcd: {x: '-1%', y: 0}}
I tried looping the object but I don't know if there is a smartest solution
const obj = {a: {x: 0, y: 0}, b: {x: 10, y: 3}, abcd: {x: -1, y: 0}}
let result = Object.fromEntries(Object.entries(obj).map(([k,v]) => {
return [k,{...v,x:`${v.x}%`}]
}))
console.log(result)
You can also check the object recursively. So no matter how deep the object goes every given key that matches gets a suffix.
I also make sure to create a copy of the object to prevent altering the original object(s).
const obj = {a: {x: 0, y: 0}, b: {x: 10, y: 3}, abcd: {x: -1, y: 0}};
const addSuffixToObj = (obj, key, suffix) => {
const copy = {...obj};
Object.keys(copy).forEach((prop) => {
if (typeof copy[prop] === 'object') {
copy[prop] = addSuffixToObj(copy[prop], key, suffix);
}else if(prop === key){
copy[prop] = copy[prop] + suffix;
}
});
return copy;
}
// Add "%" to all "x" keys
const result = addSuffixToObj(obj, 'x', '%');
console.log(result);
You can get the array of object keys and then use forEach, it's a method that executes provided function for every element of array(here - for every object key):
Object.keys(obj).forEach(el => obj[el].x = `${obj[el].x}%`)

Merge objects in array with similar key

I have an array of objects:
objArray = [
{x: 1, y: 7},
{x: 2, y: 14},
{x: 1, z: 9},
{x: 2, z: 18}
{x: 1, n: 6}
{x: 2, n: 16}
]
Is there an efficient way to merge for "X" without a for loop? so that I end up with:
objArray = [
{x: 1, y: 7, z: 9, n: 6},
{x: 2, y: 14, z: 18, n: 16}
]
So look for common objArray[n]["x"] and merge all hits into one object? It's OK to modify the original array or create a new one.
I'm aware this can be done with a loop, but I'm trying to avoid too many loops for this implementation, though I'm not sure if a reduce or a filter would work for this.
You could take a Map and group by property x.
var array = [{ x: 1, y: 7 }, { x: 2, y: 14 }, { x: 1, z: 9 }, { x: 2, z: 18 }, { x: 1, n: 6 }, { x: 2, n: 16 }],
result = Array.from(
array
.reduce((m, o) => m.set(o.x, Object.assign({}, m.get(o.x), o)), new Map)
.values()
);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
You could use reduce method to build an object and then Object.values to get an array.
const data = [{"x":1,"y":7},{"x":2,"y":14},{"x":1,"z":9},{"x":2,"z":18},{"x":1,"n":6},{"x":2,"n":16}]
const res = data.reduce((r, {x, ...rest}) => {
if(!r[x]) r[x] = {x, ...rest}
else Object.assign(r[x], rest);
return r;
}, {})
const result = Object.values(res);
console.log(result)
You can do it with Array#reduce:
const objArray = [
{x: 1, y: 7},
{x: 2, y: 14},
{x: 1, z: 9},
{x: 2, z: 18},
{x: 1, n: 6},
{x: 2, n: 16},
]
const result = Object.values( objArray.reduce(
(p,c) => (p[c.x] = Object.assign( {}, p[c.x], c ), p ), {}
) );
console.log( result );

How to push an object into an object?

So i have a object like this:
let obj = {'0': {x: 25, y: 12}, '1': {x:55, y:6} ,...}
Now How can I push an other object like {x: 12, y: 15} in to this object?
Insert your data in the last index (you can get the last index converting the object to array and getting the length)
let obj = {'0': {x: 25, y: 12}, '1': {x:55, y:6}}
obj[Object.values(obj).length] = {x: 12, y: 15}
console.log(obj)

Comparing JavaScript objects

0
:
{a: "5", b: "gg", X: "dd", Y: "dd", Z: "dd"}
1
:
{X: "dd", Y: "dd", Z: "dd"}
2
:
{X: "df", Y: "dd", Z: "dd"}
I want to compare these objects with each other so that i can not add repeated object in an array.
If I understand your question with given information, there can be 2 possible scenarios.
if you want to add one object to another object (merge) based on key than it can be done with angular.extend and the same key will be overwritten by later object keys
let inp1 = {a: "aa", b: "bb", X: "xx", Y: "yy", Z: "zz"};
let inp2 = {X: "xxx", Y: "yyy", Z: "zzz", W: "www"};
let inp3 = {X: "x3", Y: "y3", Z: "z3"};
angular.extend(inp1, inp2);
console.log("inp1", inp1);
// print {"a": "aa", "b": "bb", "X": "xxx","Y": "yyy","Z": "zzz","W": "www"}
if you simply want to compare two objects before adding into another object or (push into array) then you can do it with angular.equals
anguar.equals(inp2,inp3) // return false

Searching for an object inside an array of arrays

i have an array, filled with arrays, each containing multiple objects. I want to see if my objects exists in there
Ive made a jsfiddle to keep it simple - https://jsfiddle.net/rgnoz31y/1/
Or if you want to just see my code, its below:
blackChains = [];
blackChains.push([{x: 1, y: 2}, {x: 1, y: 3}]);
blackChains.push([{x: 3, y: 4}, {x:4, y: 4}, {x:5, y: 4}]);
currentPiece = {x: 1, y: 3};
const isInChain = blackChains.map(g => g[{}]).includes(currentPiece);
console.log(isInChain);
It currently returns false, when it should be true
As you are using Arrow functions, I assumed you are using ES6.
Using Spreads, I can create an array of all the Array Items https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/Spread_operator
acc.push(...item);
includes would usually work, however it only works on call by reference, not call by value e.g. this would have failed:
console.log([{x: 1, y: 2}, {x: 1, y: 3}].includes(currentPiece));
Some returns true, if at least one of the items matches the condition. By changing the Item and Search Element into a JSON String, we can check by Value.
blackChains = [];
blackChains.push([{x: 1, y: 2}, {x: 1, y: 3}]);
blackChains.push([{x: 3, y: 4}, {x:4, y: 4}, {x:5, y: 4}]);
currentPiece = {x: 1, y: 3};
const isInChain = blackChains.reduce((acc, item) => {
acc.push(...item);
return acc;
}, []).some(item => JSON.stringify(item) === JSON.stringify(currentPiece));
console.log(isInChain);
As commented before,
g[{}] will return undefined. It is interpreted as g["Object object"]
blackChains.map(g => g[{}]) will return an array of length n with all as undefined.
You can use recursion to loop over r nested arrays and stop it when you get Objects.
var blackChains = [];
blackChains.push([{x: 1, y: 2}, {x: 1, y: 3}]);
blackChains.push([{x: 3, y: 4}, {x:4, y: 4}, {x:5, y: 4}]);
var currentPiece = { x: 1, y: 3 };
function searchObjInArray(arr, search) {
if (Array.isArray(arr)) {
return arr.some(function(item) {
return searchObjInArray(item, search)
})
} else if (typeof arr === "object") {
var valid = true;
for (var k in search) {
valid = valid && search[k] === arr[k];
if (!valid) break;
}
return valid;
}
}
var isInChain = searchObjInArray(blackChains, currentPiece)
console.log("isInChain: ", isInChain);
currentPiece.y = 4;
isInChain = searchObjInArray(blackChains, currentPiece)
console.log("isInChain: ", isInChain);
Simply Try with Array#filter() and Array#find() used find the match with c Array
function check(c){
blackChains = [];
blackChains.push([{x: 1, y: 2}, {x: 1, y: 3}]);
blackChains.push([{x: 3, y: 4}, {x:4, y: 4}, {x:5, y: 4}]);
return blackChains.filter(a=> a.find(a=> a.x == c.x && a.y == c.y ))[0] ? true : false;
}
console.log(check({x: 1, y:3}))
console.log(check({x: 1, y:31}))
Replace with:
const isInChain = blackChains.findIndex(
i => i.findIndex(a => a.x === currentPiece.x && a.y === currentPiece.y) > -1) > -1;
You need to check key-value equality explicitly as shown below:
blackChains = [];
blackChains.push([{x: 1, y: 2}, {x: 1, y: 3}]);
blackChains.push([{x: 3, y: 4}, {x:4, y: 4}, {x:5, y: 4}]);
currentPiece = {x: 1, y: 3};
const isInChain = blackChains.map(bc => !!bc.find(o => // return true a false for each index
Object.keys(o).every(key => o[key] === currentPiece[key])));
console.log(isInChain);

Categories