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}%`)
Related
I have arr
let arr = [
{tags: {x: 2, y: 12}},
{type: {x: 23, y: 44}},
{order: {x: 5, y: 1200}},
]
and need (the same key, but value must come from current x)
let arr = [
{tags: 2},
{type: 23},
{order: 5}
]
what I try
arr.map(({ k, v }) => { [k]: v.x });
Please about help!!
let arr = [
{tags: {x: 2, y: 12}},
{type: {x: 23, y: 44}},
{order: {x: 5, y: 1200}},
]
arr.map((item) => {
const newItem = {}
newItem[ Object.keys(item)[0]] = item[Object.keys(item)[0]].x
return newItem
})
This is my solution. It's worked but I don't think it is good answer!
This should be one possible way to obtain the desired objective.
Code Snippet
let arr = [
{tags: {x: 2, y: 12}},
{type: {x: 23, y: 44}},
{order: {x: 5, y: 1200}},
];
const res = arr.flatMap(
obj => Object.entries(obj).map(
([k, {x}]) => ({ [k]: x })
)
);
console.log(res);
Explanation
Iterate over the array using .flatMap() (to avoid nested-array in the result)
Take each object (obj) and iterate over key-value pairs using Object.entries()
Now, de-structure the [key, value] iterator to directly access prop x
Transform it to an object with x as the value
You're moving in the right direction. You just need Object.entries to help you get k and v as an array [k, v].
let arr = [ {tags: {x: 2, y: 12}}, {type: {x: 23, y: 44}}, {order: {x: 5, y: 1200}} ];
const output = arr.flatMap(
o => Object.entries(o).map(([k,v]) => ({[k]:v.x}))
);
console.log( output );
Alternatively, since v has the same properties in all the elements, you can use destructuring as in the demo below:
let arr = [ {tags: {x: 2, y: 12}}, {type: {x: 23, y: 44}}, {order: {x: 5, y: 1200}} ];
const output = arr.flatMap(
o => Object.entries(o).map(([k,{x,y}]) => ({[k]:x}))
);
console.log( output );
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);
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 );
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);
How do i define updater to get true in newState.c.x === 8 and avoid any mutation in state?
var state = {
a: {x: 1, y: 1},
b: {x: 2, y: 2},
c: {x: 3, y: 3},
d: {x: 4, y: 4},
};
var key = 'c';
var x = 8;
var updater = {
//Having state, key and x here....
}
var newState = Object.assign({}, state, updater);
if(newState.c.x === 8) {
wooHoo();
}
Thanks in advance!
You can use some ES6 destructuring and Object.assign().
var state = {
a: {x: 1, y: 1},
b: {x: 2, y: 2},
c: {x: 3, y: 3},
d: {x: 4, y: 4},
};
var key = 'c';
var x = 8;
var updater = {
[key]: Object.assign({}, state[key], {x})
}
var newState = Object.assign({}, state, updater);
if(newState.c.x === 8) {
alert('True')
}