javascript array push keeps repeating it self cant find out why - javascript

I cant figure out why this arrayUnd gets repeated key values. ive been on this for three weeks. I must be doing somehthing stupid. I know they are loops. but everything works except the push. it logs when the key repeats and stuff. but it somehow is adding it to it? very confusing.
Heres my Javascript
var array = [
{"size":["12","22"]},
{"color":["blue"]},
{"design":["flower-blue"]},
{"size":["12","22","44"]},
{"color":["red"]},
{"design":["flower-blue"]}
]
//output array
arrayUnd=[
{"color":["red"]}
]
//is array?
console.log( Array.isArray(array))
function pusher(obj){
arrayUnd.push(obj)
}
function isRepeat(key,value,obj){
// console.log(key[0])
for (let item=0; item < arrayUnd.length; item++ ){
if ( arrayUnd[item].hasOwnProperty(key)){
console.log("key: " + key)
console.log("yes")
console.log(arrayUnd)
}
else{
console.log("keyno: " + key)
console.log("no")
//pusher(obj)
if ( arrayUnd[item].hasOwnProperty(key) === false){
pusher(obj)
}
console.log(arrayUnd)
}
}
}
array.forEach((obj)=>{
var a= Object.keys(obj)
var b= Object.values(obj)
isRepeat(a,b,obj)
})
console.log(arrayUnd)

Your loop is checking all objects to see if they don't match. At least one of them won't match, so it will try to push that many times. You need to check all elements, and after checking them all for existence decide if you want to push or not.
Current logic is equivalent to: if anything in arrUnd doesn't match, push me each time I check.
some works here, because it checks if anything matches, and returns true or false, which you can then use to decide if you want to push or not (only once, after I've found if anything in the array matches, deciding using the final result).
Using some to check if any other element with same key exists. Push if nothing found.
var array = [{
"size": ["12", "22"]
},
{
"color": ["blue"]
},
{
"design": ["flower-blue"]
},
{
"size": ["12", "22", "44"]
},
{
"color": ["red"]
},
{
"design": ["flower-blue"]
}
]
//output array
arrayUnd = [{
"color": ["red"]
}]
//is array?
console.log(Array.isArray(array))
function pusher(obj) {
arrayUnd.push(obj)
}
function isRepeat(key, value, obj) {
if(!arrayUnd.some(x => x.hasOwnProperty(key[0])))
arrayUnd.push(obj)
}
array.forEach((obj) => {
var a = Object.keys(obj)
var b = Object.values(obj)
isRepeat(a, b, obj)
})
console.log(arrayUnd)

You are passing an array to isRepeat instead of the key and value of the object.
Object.keys() returns an array, even if the object only has one key.
When you check if ( arrayUnd[item].hasOwnProperty(key) === false), arrayUnd[item].hasOwnProperty(key) will always be false, so the object will always get pushed to your array.
You can fix this by accessing the first key and value of each object:
array.forEach((obj)=>{
var a= Object.keys(obj)
var b= Object.values(obj)
isRepeat(a[0],b[0],obj)
})

The reason your code keeps pushing object to arrayUnd it's because when it iterates through the array it checks for the array key if its present if not it pushes it to arrayUnd, now you have 2 problems first you are not actually checking for the array key to match you comparing object so you will always get false , and second is that each time you push to the array the length of your array grow and so the number of iterations increases
you can achieve this in two lines of code
var array = [
{"size":["12","22"]},
{"color":["blue"]},
{"design":["flower-blue"]},
{"size":["12","22","44"]},
{"color":["red"]},
{"design":["flower-blue"]}
]
//output array
arrayUnd=[
{"color":["red"]}
]
array.forEach(p=>Object.entries(p).forEach(p=>{
!arrayUnd.some(o=>o.hasOwnProperty(p[0])) ? arrayUnd.push({[p[0]]:p[1]}):null
}))
console.log(arrayUnd)

var inpAry = [
{ "size": ["12", "22"] },
{ "color": ["blue"] },
{ "design": ["flower-blue"] },
{ "size": ["12", "22", "44"] },
{ "color": ["red"] },
{ "design": ["flower-blue"] }
];
var opAry = [
{ "color": ["red"] }
];
inpAry.forEach(inpAryElem => {
var ipAryElemKeys = Object.keys(inpAryElem);
var ipAryElemVals = Object.values(inpAryElem);
ipAryElemKeys.forEach((ipAryElmKey,ipAryElemKyIdx) => {
var isKeyPresent = false;
opAry.forEach(opAryElem => {
if(opAryElem[ipAryElmKey]) {
isKeyPresent = true;
opAryElem[ipAryElmKey].push(...ipAryElemVals[ipAryElemKyIdx]);
}
});
if(!isKeyPresent) {
opAry.push({[ipAryElmKey]:ipAryElemVals[ipAryElemKyIdx]});
}
})
});
console.log(opAry);

Related

How to convert JSON to a key-value dictionary using typescript?

I have the following json example:
{
"MyTest:": [{
"main": {
"name": "Hello"
},
"test2": {
"test3": {
"test4": "World"
},
"test5": 5
}
},
{
"main": {
"name": "Hola"
},
"test6": [{
"name": "one"
},
{
"name": "two"
}
]
}
]
}
I'm trying to convert it to an array of arrays with key-values
[[main.name: "Hello",test2.test3.test4: "World", test2.test5: 5] ,
[main.name = "Hola", test6.name: "one", test6.name: "two"] ];
Looking for some function like "is leaf" - so I will know that is the value.
Any advise for deep iteration will be very appriciated.
The flattenObject() function returns an object of one level, with the keys built from all sub keys. The recursive function checks if the current value is an object. If it is, it iterates the object with _.flatMap() and calls itself on each property with the keys collected so far. If the value is not an object, it returns an object with a single property (the joined keys), and the value.
It then merges the array of { key: value } objects to a single object.
const flattenObject = val => {
const inner = (val, keys = []) =>
_.isObject(val) ? // if it's an object or array
_.flatMap(val, (v, k) => inner(v, [...keys, k])) // iterate it and call fn with the value and the collected keys
:
{ [keys.join('.')]: val } // return the joined keys with the value
return _.merge({}, ...inner(val))
}
const obj = {"MyTest":[{"main":{"name":"Hello"},"test2":{"test3":{"test4":"World"},"test5":5}},{"main":{"name":"Hola"},"test6":[{"name":"one"},{"name":"two"}]}]}
const result = obj.MyTest.map(flattenObject)
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.js"></script>

Why does this recursive flatten array function gives me wrong result? Javascript [duplicate]

This question already has answers here:
Is Chrome’s JavaScript console lazy about evaluating objects?
(7 answers)
Closed 3 years ago.
I'm working on flatten array function. It takes an input like this
const input = [
{
"value": "value0",
"children": []
},
{
"value": "value1",
"children": [
{
"value": "value2",
"children": [
{
"value": "value3",
"children": []
}
]
},
{
"value": "value4",
"children": []
}
]
},
{
"value": "value5",
"children": []
},
{
"value": "value6",
"children": []
}
];
and return an array
[
{"value":"value0"},
{"value":"value1"},
{"value":"value2"},
{"value":"value3"},
{"value":"value4"},
{"value":"value5"},
{"value":"value6"}
]
I have solved this problem. Here is my former wrong code and I was trying to debug it
function flatArray(input) {
if(input.length === 0) return [];
let res = [];
input.forEach(i => {
for(let key of Object.keys(i)) {
if(key === 'value') {
res.push({[key]: i[key]});
} else {
const arr = flatArray(i[key]);
res.concat(arr);
console.log(res);
}
}
});
return res;
}
PS: It's wrong because the misuse of concat
The output is weird. I got
I'm wondering why the first three are type of object? And why, like the first output, can get an array with 4 elements instead of getting an array with only {value: value0}?
I guess it has something to do with closures but I can't explain this thing. Can anyone help me?
Well, it looks like you answered yourself:
PS: It's wrong because the misuse of concat
The concat method won't change the existing arrays, but return a new one. So you have to assign its output to you res variable:
function flatArray(input) {
if(input.length === 0) return [];
let res = [];
input.forEach(i => {
for(let key of Object.keys(i)) {
if(key === 'value') {
res.push({[key]: i[key]});
}
else {
const arr = flatArray(i[key]);
res = res.concat(arr);
}
}
});
return res;
}
If the order of objects in the output doesn't matter, I would structure this differently. Put the top array elements into input and traverse each object in input: for each object, remove the array valued-keys and concat them to input and push the non-array-valued object to res. Continue iteration until input is empty. You could output the same ordering by inserting each child list to the head of input for depth-first traversal. Sorry I didn't actually answer how to fix the recursive one.

How can I get data iterate Json?

I need get data the my Json but I can't use 'key' because the 'key' is different each day.
I tried :
template: function(params) {
const objects = JSON.parse(JSON.stringify(params.data.masterdetail));
for (const obj of objects) {
const keys = Object.keys(obj);
const cont = 0;
keys.forEach(key => {
const valor = obj[key];
console.log('value ', valor[0]);
});
}
I first tried with 0 and then use cont, but with 0 console.log (value is undefined)....
If I use console.log ('value' , valor['name']) IT'S OK ! but I can't use keys and if I use valor[0] is undefined...........
Example Json
{
"headers": [
"headerName": "asdasd",
], //end headers
"datas": [
"idaam": "11",
"idorigen": "11",
"masterdetail": [{
"child1": {
"name": "I AM",
"age": "1"
},
"child2": {
"name": "YOU ARE",
"age": "2"
},
"child3": {
"name": "HE IS",
"age": "3"
},
}] //end masterdetail
]//end datas
}//end JSON
Edit :
I can't use 'keys' because today I receive "name", "typeval" etc. and tomorrow I can get 'surname','id' etc.
If you see in my first img you can see "4" bits of data.
1º obj[key]{
name = "adopt",
typeval= "",
etc
}
2º obj[key]{
"link" = "enlace",
"map" = "map"
etc
}
If I use this code : I get "name" OKEY but
I HAVE PROHIBITED use of value['name'] or value[typeval] because this Json always is dynamic.
var objects = params.data.masterdetail[0];
const keys = Object.keys(objects);
let value;
keys.forEach(key => {
value = objects[key];
console.log(value['name']);
console.log(value['typeval']);
});
I need for example :
var objects = params.data.masterdetail[0];
const keys = Object.keys(objects);
cont = 0 ;
keys.forEach(key => {
value = objects[key];
console.log(value[0]);
});
but value[0] is undefined and then when I arrive 2ºobj[key] link is index 0 but cont maybe is .... 4...
Sorry for my English...
To simply print the objects within the first entry in the masterdetail array, you can do the following:
var objects = params.datas.masterdetail[0];
const keys = Object.keys(objects);
keys.forEach(key => {
console.log('value ', objects[key]);
});
Based on a (suitably corrected - see my comments above) version of the JSON above, this would produce console output as follows:
value {name: "I AM", age: "1"}
value {name: "YOU ARE", age: "2"}
value {name: "HE IS", age: "3"}
Unfortunately it's not 100% clear from the question if this is the output you were looking for, but that's my best guess based on the code.
Your main mistakes were that
1) masterdetail is an array, and all the data is within the first element of that array, so to get the objects within it you need to select that element first. If the array can have multiple elements in real life then you'd need an outer loop around the code above to iterate through it.
2) If you're looping through the keys of an object, you don't need to also iterate through the properties a different way. You seemed to have two loops designed to do the same thing.

how to get unique values from array of objects with addition of numbers

I'm working in wso2 carbon dashboard. My table is containing 2 fields (Name and Number). I Have duplicate name in the objects but with different number. I want unique name with addition of numbers.
[
{
"Name":"Abc",
"number":2
},
{
"Name":"bcd",
"number":3
},
{
"Name":"Abc",
"number":5
}
]
expected output
[
{
"name":"Abc",
"Number":7
},
{
"name":"bcd",
"Number":3
}
]
I'm using java script to achieve such task. please help me
Use Array#reduce method with a reference object.
var data = [{
"Name": "Abc",
"number": 2
}, {
"Name": "bcd",
"number": 3
}, {
"Name": "Abc",
"number": 5
}];
// object for index reference
var ref = {};
// iterate and generate the array
var res = data.reduce(function(arr, o) {
// check index already defined
if (!(o.Name in ref)) {
// if not defined then define index
ref[o.Name] = arr.length;
// and push the element
// you can also use
// arr.push({Name:o.Name, number:o.number});
arr.push(Object.assign({}, o));
} else {
// if index already defined update the number
arr[ref[o.Name]].number += o.number;
}
// return the array reference
return arr;
// set initial value as empty array
}, []);
console.log(res);

Filtering array of Objects Using Lodash or Javascript based on property name

I am Having the Array of objects. Like this
var result=[{"batchId":123, "licenseId":2345ef34, "name":"xxx"},
{"batchId":345, "licenseId":2345sdf334, "name":"www"},
{"batchId":145, "licenseId":234sdf5666, "name":"eee"},
{"batchId":455, "licenseId":asfd236645 },
{"batchId":678, "name":"aaa"}]
i want to have the array which is contains all the three properties. the Output should be like this.
[{"batchId":123, "licenseId":2345ef34, "name":"xxx"},
{"batchId":345, "licenseId":2345sdf334, "name":"www"},
{"batchId":145, "licenseId":234sdf5666, "name":"eee"}]
can anybody Help me on this
This is simple with the array .filter() method:
var result=[
{"batchId":123, "licenseId":"2345ef34", "name":"xxx"},
{"batchId":345, "licenseId":"2345sdf334", "name":"www"},
{"batchId":145, "licenseId":"234sdf5666", "name":"eee"},
{"batchId":455, "licenseId":"asfd236645" },
{"batchId":678, "name":"aaa"}
];
var filtered = result.filter(function(v) {
return "batchId" in v && "licenseId" in v && "name" in v;
});
console.log(filtered);
The function you pass to .filter() is called for each element in the array. Each element for which you return a truthy value will be included in the resulting array.
In the code above I simply test if all three of those specific properties are present, although there are other tests you could use that would get the same result for that data:
var result=[ {"batchId":123, "licenseId":"2345ef34", "name":"xxx"}, {"batchId":345, "licenseId":"2345sdf334", "name":"www"}, {"batchId":145, "licenseId":"234sdf5666", "name":"eee"}, {"batchId":455, "licenseId":"asfd236645" }, {"batchId":678, "name":"aaa"} ];
var filtered = result.filter(function(v) {
return Object.keys(v).length === 3;
});
console.log(filtered);
Note that you need to put your licenseId values in quotes, because they seem to be string values.
var result = [{
"batchId": 123,
"licenseId": '2345ef34',
"name": "xxx"
}, {
"batchId": 345,
"licenseId": '2345sdf334',
"name": "www"
}, {
"batchId": 145,
"licenseId": '234sdf5666',
"name": "eee"
}, {
"batchId": 455,
"licenseId": 'asfd236645'
}, {
"batchId": 678,
"name": "aaa"
}];
function hasProperties(object) {
return object.hasOwnProperty('batchId') && object.hasOwnProperty('licenseId') && object.hasOwnProperty('name')
}
result.filter(e => hasProperties(e));

Categories

Resources