Get only 1 object from array with 2 similar objects - javascript

As you can see here I have an array of 2 objects which have the same name and other elements, instead of x,y. I'm trying to console log them, and it works just fine, am getting 2 objects. My question is, how do I console.log only one of them, the first one?
var _hero = [{
nick: "Mike",
lvl: 500,
x: 10,
y: 10
}, {
nick: "Mike",
lvl: 500,
x: 15,
y: 15
}]
let main = () => {
_hero.forEach(function(_hero) {
if (_hero.nick == "Mike") {
console.log(_hero);
}
});
};
main();

Use array.find that will give you only the first matching element
var _hero = [{
nick: "Mike",
lvl: 500,
x: 10,
y: 10
}, {
nick: "Mike",
lvl: 500,
x: 15,
y: 15
}]
console.log(_hero.find(data=>data.nick ==='Mike'));

Use second parameter in forEach(function(hero, i){... to check the iteration like the following:
var _hero = [{
nick: "Mike",
lvl: 500,
x: 10,
y: 10
}, {
nick: "Mike",
lvl: 500,
x: 15,
y: 15
}]
let main = () => {
_hero.forEach(function(_hero,i) {
if (_hero.nick == "Mike" && i == 0) {
console.log(_hero);
}
});
};
main();

Related

How to apply custom formatting for a JSON stringify?

I have the following code:
const sample = [
{
name: "apple",
points: [ { x: 1, y: 2 }, { x: 3, y: 4 }, { x: 5, y: 6 }, { x: 7, y: 8 } ],
age: 24
},
{
name: "banana",
points: [ { x: 1, y: 2 }, { x: 3, y: 4 }, { x: 5, y: 6 }, { x: 7, y: 8 } ],
age: 45
}
];
const qwer = JSON.stringify(sample, null, 2);
console.log(qwer);
If you run it, you'll notice it has nice formatting, except for the points array, which is extremely verbose.
I would like everything to be indented like normally (which is why I'm passing in 2 for the final parameter to stringify), but I would like the points array to only take a single line, like how it is declared in the code.
The reason for this is because currently each points array is stretched to like 18 lines, when there will only ever be 3 or 4 items. I would like them to stay on one line.
I tried to use a custom replacer, and while it somewhat worked, it forced the JSON array to be a string. But it's not a string. I want it to stay an array.
Is there any way to do this?
For the general solution, a mini parser would be the best approach, but a quick but ugly-looking approach would be to use a replacer to replace arrays with stringified strings with a unique value as a prefix which can be replaced afterwards.
const sample = [
{
name: "apple",
age: 24,
points: [ { x: 1, y: 2 }, { x: 3, y: 4 }, { x: 5, y: 6 }, { x: 7, y: 8 } ],
},
{
name: "banana",
age: 45,
points: [ { x: 1, y: 2 }, { x: 3, y: 4 }, { x: 5, y: 6 }, { x: 7, y: 8 } ],
}
];
const withNestedStringifiedArrays = JSON.stringify(
sample,
(key, value) => key && Array.isArray(value) ? '##UNIQUE##' + JSON.stringify(value) : value,
2
);
const output = withNestedStringifiedArrays.replace(
/"##UNIQUE##(.*?)"(,)?$/gm,
(_, stringifiedArr, possibleComma = '') => stringifiedArr.replaceAll('\\', '') + possibleComma
);
console.log(output);

How to store separately the repeated values inside array of objects

I have this array of objects in Javascript:
var arrayData = [
{ id: "0", x: -1, y: 38},
{ id: "1", x: -2.7823, y: 43.444},
{ id: "2", x: -1.1654, y: 38.12088},
{ id: "3", x: -1, y: 38},
{ id: "4", x: -2.7823, y: 43.444 },
{ id: "5", x: -1.1654, y: 38.12088},
{ id: "6", x: -1.1654, y: 38.12088},
]
and i'd need to check what objects have the same property x and y and someway store this objects separately so i can access later to them.
i've got this:
var copy = arrayData.slice(0);
// first loop goes over every element
for (var i = 0; i < arrayData.length; i ++) {
// loop over every element in the copy and see if it's the same
for (var w = i + 1; w < copy.length; w++) {
if ((arrayFotos[i].x === copy[w].x) && (arrayFotos[i].y === copy[w].y)) {
if(!duplicates.includes(arrayFotos[i].id))
duplicates.push(arrayFotos[i].id);
if(!duplicates.includes(copy[w].id))
duplicates.push(copy[w].id);
}
}
This returns me an array with all ids of the objects which
have repeated x and y properties but i need a way to store
them separately so i have: [0,3][1,4][2,5,6]. Is there any
way to do it? Thanks if u want to help me.
You could take a hash table and collect id for same coordinates.
var arrayData = [{ id: "0", x: -1, y: 38 }, { id: "1", x: -2.7823, y: 43.444 }, { id: "2", x: -1.1654, y: 38.12088 }, { id: "3", x: -1, y: 38 }, { id: "4", x: -2.7823, y: 43.444 }, { id: "5", x: -1.1654, y: 38.12088 }, { id: "6", x: -1.1654, y: 38.12088 }],
duplicates
hashtable = {};
for (var i = 0; i < arrayData.length; i++) {
let key = ['x', 'y'].map(k => arrayData[i][k]).join('|');
hashtable[key] = hashtable[key] || [];
hashtable[key].push(arrayData[i].id);
}
duplicates = Object.values(hashtable);
console.log(duplicates);

Flatten nested JavaScript object

I have a nested object and I want to flatten/map it into a single-layered, table-like object.
[{
a: 1,
b: 2,
c: [{
x: 10,
y: 20
}, {
x: 30,
y: 40
}]
}, {
a: 3,
b: 4,
c: [{
x: 50,
y: 60
}, {
x: 70,
y: 80
}]
}]
From that, I want to get something like this:
[{
a: 1,
b: 2,
x: 10,
y: 20
}, {
a: 1,
b: 2,
x: 30,
y: 40
}, {
a: 3,
b: 4,
x: 50,
y: 60
}, {
a: 3,
b: 4,
x: 70,
y: 80
}]
Sure, I could simply iterate over the object with two for loops and put the result info a separate array, but I wonder, if there is a simpler solution. I already tried to play around with flatMap. It works, if I only want the c portion of my nested object, but I don't know how to map a and b to this object.
As some of you asked for some working code, this should do it (untested):
let result = [];
for (const outer of myObj)
for (const inner of outer.c)
result.push({a: outer.a, b: outer.b, x: inner.x, y: inner.y});
The question is, if there is a functional one-liner or even another, better approach. In reality, my object consists of four layers and the nested for loops become messy quite fast.
You may use flatMap method alongwith map on property 'c':
var input = [{ a: 1, b: 2, c: [{ x: 10, y: 20 }, { x: 30, y: 40 }] }, { a: 3, b: 4, c: [{ x: 50, y: 60 }, { x: 70, y: 80 }] }];
const output = input.flatMap(obj =>
obj.c.map(arr => ({a: obj.a, b: obj.b, x: arr.x, y: arr.y}))
);
console.log(output);
Ideally a solution would require something to tell how far down to start classing the object as been a full object, a simple solution is just to pass the level you want. If you don't want to pass the level, you could do a check and if none of the properties have array's, then you would class this as a complete record, but of course that logic is something you would need to confirm.
If you want a generic version that works with multiple levels were you pass the level & using recursion you could do something like this ->
const a=[{a:1,b:2,c:[{x:10,y:20},{x:30,y:40}]},{a:3,b:4,c:[{x:50,y:60},{x:70,y:80}]}];
function flattern(a, lvl) {
const r = [];
function flat(a, l, o) {
for (const aa of a) {
o = {...o};
for (const [k, v] of Object.entries(aa)) {
if (Array.isArray(v) && l < lvl) flat(v, l + 1, o);
else o[k] = v;
}
if (l === lvl) r.push(o);
}
}
flat(a, 1);
return r;
}
console.log(flattern(a, 2));
//console.log(flattern(a, 1));
A flatMap solution would look like this:
const result = myObj.flatMap(outer =>
outer.c.map(inner =>
({a: outer.a, b: outer.b, x: inner.x, y: inner.y})
)
);
Of course, if your object has multiple layers, not just two, and possibly even multiple or unknown properties that have such a nesting, you should try to implement a recursive solution. Or an iterative one, where you loop over an array of property names (for your example case, ["c"]) and apply the flattening level by level.
One of the solution using reduce is:
const list = [{
a: 1,
b: 2,
c: [{
x: 10,
y: 20
}, {
x: 30,
y: 40
}]
}, {
a: 3,
b: 4,
c: [{
x: 50,
y: 60
}, {
x: 70,
y: 80
}]
}]
const flatten = (arr) => {
return arr.reduce((flattened, item) => {
return [
...flattened,
...item.c.reduce((flattenedItem, i) => {
return [
...flattenedItem,
{
a: item.a,
b: item.b,
x: i.x,
y: i.y
}
]
}, [])
]
}, [])
}
console.log(flatten(list));
Using two reducers to flatten your structure
const input = [{
a: 1,
b: 2,
c: [{
x: 10,
y: 20
}, {
x: 30,
y: 40
}]
}, {
a: 3,
b: 4,
c: [{
x: 50,
y: 60
}, {
x: 70,
y: 80
}]
}]
const result = input.reduce((acc_0, x) => {
return [...acc_0, ...x.c.reduce((acc_1, y) => {
const obj = {
a: x.a,
b: x.b,
x: y.x,
y: y.y
}
acc_1.push(obj);
return acc_1;
}, [])]
}, []);
console.log(result)

Push an object at a key in an object array javascript

I have an array that stores various objects. Looks like following:
[ 'key2': { id: 'WA3WA9WA2WA4WAdWA1WA2WAb-WAeWAdWAaWAf-4WA1WAaWA6-WA8WA8WAeWAc-WAfWAdWAbWAeWAaWA5WA1WAfWAbWAdWAfWA2',
d: undefined,
x: 520,
y: 120 },
'Key1': { id: 'WA7WA2WAbWAdWAfWA9WA6WA8-WA7WAdWAeWA4-4WA4WA3WAb-WAaWAdWA4WAe-WA2WAbWAdWA5WA1WA0WA7WAbWA3WAdWAfWA9',
d: undefined,
x: 810,
y: 180 } ]
How do I push a value into the array such as:
['key3':{id:something, d:undefined,x:200,y:400}]
Here Key1, Key2, Key3 are all dynamically created and stored in a variable.
maybe You mean You have a literal like
var yourObj = { 'key1': ...
'key2': ...
}
and You want to push another one? if it's the case do it
yourObj[newKeyGenerated] = theNewObj;
You can have an array
var a = [{ id: 'WA3WA9WA2WA4WAdWA1WA2WAb-WAeWAdWAaWAf-4WA1WAaWA6-WA8WA8WAeWAc-WAfWAdWAbWAeWAaWA5WA1WAfWAbWAdWAfWA2',
d: undefined,
x: 520,
y: 120 },
{ id: 'WA7WA2WAbWAdWAfWA9WA6WA8-WA7WAdWAeWA4-4WA4WA3WAb-WAaWAdWA4WAe-WA2WAbWAdWA5WA1WA0WA7WAbWA3WAdWAfWA9',
d: undefined,
x: 810,
y: 180 } ]
in this case a.push({...})
or an object
var a = { 'key2': { id: 'WA3WA9WA2WA4WAdWA1WA2WAb-WAeWAdWAaWAf-4WA1WAaWA6-WA8WA8WAeWAc-WAfWAdWAbWAeWAaWA5WA1WAfWAbWAdWAfWA2',
d: undefined,
x: 520,
y: 120 },
'Key1': { id: 'WA7WA2WAbWAdWAfWA9WA6WA8-WA7WAdWAeWA4-4WA4WA3WAb-WAaWAdWA4WAe-WA2WAbWAdWA5WA1WA0WA7WAbWA3WAdWAfWA9',
d: undefined,
x: 810,
y: 180 } }
and then you can have a.key3 = {...}
If I have understood correctly , this should be the solution : https://jsfiddle.net/a7uxd4tk/
var data1 = [ {'key1': { id: 'a', d: undefined, x: 520, y: 120 }}];
var data2 = [ {'key2': { id: 'b', d: undefined, x: 520, y: 120 }}];
var data3 = [ {'key3': { id: 'b', d: undefined, x: 520, y: 120 }}];
var addData = [];
addData.push(data1[0]);
addData.push(data2[0]);
addData.push(data3[0]);
console.log(addData);
Also do note [ { and } ]
Try it:
var data = [ {'key2': { id: 'WA3WA9WA2WA4WAdWA1WA2WAb-WAeWAdWAaWAf-4WA1WAaWA6-WA8WA8WAeWAc-WAfWAdWAbWAeWAaWA5WA1WAfWAbWAdWAfWA2',
d: undefined,
x: 520,
y: 120 }},
{'Key1': { id: 'WA7WA2WAbWAdWAfWA9WA6WA8-WA7WAdWAeWA4-4WA4WA3WAb-WAaWAdWA4WAe-WA2WAbWAdWA5WA1WA0WA7WAbWA3WAdWAfWA9',
d: undefined,
x: 810,
y: 180 }} ];
var newObj = {};
newObj.key3 = {};
newObj.key3.id = 'WA3WA9WA2WA4WAdWA1WA2WAb-WAeWAdWAaWAf-4WA1WAaWA6-WA8WA8WAeWAc-WAfWAdWAbWAeWAaWA5WA1WAfWAbWAdWAfWA2';
newObj.key3.d = undefined;
newObj.key3.x = 520;
newObj.key3.y= 120;
data.push(newObj);
console.log(data);

Selecting a 'property value' from an array based on another 'property value' in javascript

I have an array like this.
var nodes = [{ID:"101", x:100, y:200}
,{ID:"102", x:200, y:200}
,{ID:"103", x:300, y:300}
,{ID:"104", x:200, y:300}];
I'd like to have a function which takes node's ID as input and return its (x,y).
For example, the function coordinates(103)should read the array (nodes) and return x = 300, y = 300 when it's called. Any pointer is appreciated. Thanks :)
This is what I have so far. It works but I'd like to know neater and tidier methods.
function coordinates(id){
for (var i=0 in nodes){
if(nodes[i].ID == id){
return { x: nodes[i].x, y: nodes[i].y};
}
}
}
console.log(coordinates(102));
basically you're looking at something like this
var f = function(id){
var match = nodes.filter(function(d){
return d.ID === id;
})
return match && match.length && {x: match[0].x, y:match[0].y}
|| {x: undefined, y: undefined};
};
then f('101') outputs {x: 100, y:200} and if cannot find a match then it will output {x: undefined, y: undefined}
You can use .filter, like so
var nodes = [{
ID: "101",
x: 100,
y: 200
}, {
ID: "102",
x: 200,
y: 200
}, {
ID: "103",
x: 300,
y: 300
}, {
ID: "104",
x: 200,
y: 300
}];
function coordinates(nodes, id) {
var result = nodes.filter(function (el) {
return +el.ID === id;
});
if (result && result.length) {
result = result[0];
return {
x: result.x,
y: result.y
};
}
return null;
}
console.log(coordinates(nodes, 103));
See comments inline:
Demo
var nodes = [{
ID: "101",
x: 100,
y: 200
}, {
ID: "102",
x: 200,
y: 200
}, {
ID: "103",
x: 300,
y: 300
}, {
ID: "104",
x: 200,
y: 300
}];
var noOfCord = nodes.length;
var coordinates = function(id) {
for (var i = 0; i < noOfCord; i++) {
if (nodes[i].ID == id) {
return {
x: nodes[i].x,
y: nodes[i].y
};
}
}
}
document.write(coordinates(103).x + ', ' + coordinates(103).y);
Using array filter, Try:
function coordinates(id){
return nodes.filter(function(e){ return e.ID == id })[0]
}
var nodes=[{ID:"101",x:100,y:200},{ID:"102",x:200,y:200},{ID:"103",x:300,y:300},{ID:"104",x:200,y:300}];
var result = coordinates("103");
document.write("<pre>" + JSON.stringify(result, null, 3));
Brilliant solutions with concrete JavaScript have already been proposed by people here. So I propose another alternative using underscore.js, just in case you're curious.
function coordinates(id){
var n = _.findWhere(nodes, {ID: id});
return {x: n.x, y: n.y }
}

Categories