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 );
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'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}%`)
Trying to match each element of an array to a set of coordinates in a multidimensions array in the following manner:
array1= [0, 5, 4]
array2 = [
{x: 1, y: 4, name: 'A', w: 0},
{x: 2, y: 8, name: 'E', w: 4},
{x: 3, y: 1, name: 'F', w: 5}];
I am hoping to match each element of array 1 to the value of w in array 2
0 -> {x: 1, y: 4, name: 'A', w: 0}
5 -> {x: 3, y: 1, name: 'F', w: 5}
4 -> {x: 2, y: 8, name: 'E', w: 4}
I want to return :
[
{x:1, y,4}, {x:3, y:1},
{x:3, y:1}, {x:2, y:8},
...
];
You should return the required x and y coordinates as an array.
Please find a working fiddle for that.
const array1 = [0, 5, 4]
const array2 = [
{ x: 1, y: 4, name: 'A', w: 0 },
{ x: 2, y: 8, name: 'E', w: 4 },
{ x: 3, y: 1, name: 'F', w: 5 },
];
const tempArray = array1.map((item) => array2.find((node) => node.w === item));
// console.log(tempArray);
const finalArray = tempArray.map((currentNode, index, actualArray) => {
const nextIndex = index === actualArray.length - 1 ? 0 : index + 1;
return [
{ x: currentNode.x, y: currentNode.y },
{ x: actualArray[nextIndex].x, y: actualArray[nextIndex].y },
];
});
console.log(finalArray);
You can chain array filter and map to do something like this
Array.prototype.filter() to filter all elements based on the index from first array and
Array.prototype.map() to modify the object so as to only show the x and y co-ordinates
const array1 = [0, 5, 4];
const array2 = [
{ x: 1, y: 4, name: "A", index: 0 },
{ x: 2, y: 8, name: "E", index: 4 },
{ x: 3, y: 1, name: "F", index: 5 },
];
const newArr = array2.filter(x => array1.includes(x.index)).map(x => ({ x: x.x, y: x.y }));
console.log(newArr)
This question already has answers here:
Find maximum value of property in object of objects
(3 answers)
Closed 5 years ago.
i have an array like this,and want to find index of maximum of value .for this sample it should return c1:
var arr={
c1:{val: 9, x: 2, y: 0}
c2:{val: 1, x: 3, y: 0}
c3:{val: 6, x: 4, y: 0}
}
var arr=[{val: 9, x: 2, y: 0},
{val: 1, x: 3, y: 0},
{val: 6, x: 4, y: 0}
];
var max_value = arr.reduce((a,b)=> (a.x+a.y+a.val) > (b.x+b.y+b.val) ? a:b )
// or if it is the index that you want :
var max_index = arr.reduce((a,b,i,_)=> (_[a].x+_[a].y+_[a].val) > (b.x+b.y+b.val) ? a:i, 0);
console.log(max_value);
console.log(max_index);
Assuming your array is
var arr = [
{val: 9, x: 2, y: 0}, {val: 1, x: 3, y: 0}, {val: 6, x: 4, y: 0},
];
You can get the max value by using Math.max.apply and map
var output = Math.max.apply( null, arr.map( c => c.val ) )
Or if it is an object (as per your latest update)
var arr = {
c1:{val: 9, x: 2, y: 0},
c2:{val: 1, x: 3, y: 0},
c3:{val: 6, x: 4, y: 0}
};
var maxValue = Math.max.apply( null, Object.values( arr ).map( c => c.val ) )
You can get the index-Of the maxValue by doing
var output = Object.keys(arr).findIndex( s => arr[s].val == maxValue );
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);