Trying to get my head around the maths for this one. I have a grid in which I want to know far away the block is from the center.
I have a function which currently is the following:
let grid = [];
function buildGrid(c, r) {
for(let i = 1; i <= r; i++) {
for(let j = 1; j <= c; j++) {
}
}
}
buildGrid(5, 3);
What I want it to grid to output is the following:
let grid = [{x: -2, y: -1},
{x: -1, y: -1},
{x: 0, y: -1},
{x: 1, y: -1},
{x: 2, y: -1},
{x: -2, y: 0},
{x: -1, y: 0},
{x: 0, y: 0},
{x: 1, y: 0},
{x: 2, y: 0},
{x: -2, y: 1},
{x: -1, y: 1},
{x: 0, y: 1},
{x: 1, y: 1},
{x: 2, y: 1}];
Or
-2, -1 | -1, -1 | 0, -1 | 1, -1 | 2, -1
-------|--------|-------|-------|-------
-2, 0 | -1, 0 | 0, 0 | 1, 0 | 2, 0
-------|--------|-------|-------|-------
-2, 1 | -1, 1 | 0, 1 | 1, 1 | 2, 1
Any help will be greatly appreciated.
Answer for positive flow like buildGrid(5, 3) or buildGrid(7, 5) or buildGrid(5, 3) , means even number greater then 1 no other condition added. I assume you can do this at your self. If you get and issue share all conditions with sample data.
function buildGrid(c, r) {
var c_less = (c-1)/2;// You need to modify here to add all condition
var r_less = (r-1)/2;// You need to modify here to add all condition
//console.log(c_less);
var newArr = [];
for(let j = -r_less; j <= r_less; j++) {
var str = [];
for(let i = -c_less; i <= c_less; i++) {
str.push({x:i,y:j});
}
newArr.push(str);
}
document.querySelector("#output").innerHTML = JSON.stringify(newArr);
console.log(newArr);
}
buildGrid(5, 3);
<div id="output"></div>
var c_less = (c-1)/2;// You need to modify here to add all other conditions
Related
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}%`)
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 of point objects:
const points = [ {x: 0, y: 0 }, { x: 1, y: 1}, ...]
I want to convert them to arrays of x and y:
const x = [0, 1, ...];
const y = [0, 1, ...];
I could use 2 maps:
const x = points.map(v => v.x);
const y = points.map(v => v.y);
But that needs 2 iterations over the array. I can do a loop:
const x = [];
const y = [];
for (let i = 0; i < points.length; ++i) {
const pt = points[i];
x.push(pt.x);
y.push(pt.y);
}
That seems overly verbose and potentially slow (all those push backs).
Is there a better method?
At least you need some pushing to the wanted result sets. This solution uses an object for pushing to the right array.
const
points = [{ x: 0, y: 0 }, { x: 1, y: 1 }],
x = [],
y = [],
values = { x, y };
points.forEach(o => Object.entries(o).forEach(([k, v]) => values[k].push(v)));
console.log(x);
console.log(y);
Basically the same, but with known keys.
const
points = [{ x: 0, y: 0 }, { x: 1, y: 1 }],
x = [],
y = [],
values = { x, y },
keys = Object.keys(values);
points.forEach(o => keys.forEach(k => values[k].push(o[k])));
console.log(x);
console.log(y);
While you can do this reasonably easily, say like this:
const points = [{x: 1, y: 2}, {x: 2, y: 3}, {x: 3, y: 5}, {x: 4, y: 7}, {x: 5, y: 11}]
const {x, y} = points.reduce(
({x, y}, pt) => ({x: [...x, pt.x], y: [...y, pt.y]}),
{x: [], y: []}
)
console.log(x)
console.log(y)
there is the bigger question you need to consider of why you want to do this. The original structure is flexible and useful, and you already have it in memory. The new structures depends upon shared indices, which is often difficult to work with and can easily get out of sync. Is there a strong reason not to use the original structure?
Ok, you can do make something like that :
const points = [ {x: 0, y: 0 }, { x: 1, y: 1}];
const t = points.map(item => {
return Object.values(item);
})
const x = t[0];
const y = t[1];
console.log(x,y);
var x= [], y = [], points = [{ x: 0, y: 0 }, { x: 1, y: 10 }];
points.forEach(({x: x1, y: y1}) => (x.push(x1), y.push(y1)))
console.log(x, y)
You can use array#reduce to accumulate result in a multi-dimensional array.
const points = [ {x: 0, y: 0 }, { x: 1, y: 1}],
[x,y] = points.reduce((r,o) => {
Object.values(o).forEach((v,i) => r[i].push(v));
return r;
},[[],[]]);
console.log(x);
console.log(y);
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);