Create an array of array's of object from Nested Objects - javascript

Suppose We have an Array with array of objects like
let array = [
[{value:'a',somepros:"old"}],
[{value:'d',somepros:"old"}],
[{value:'b',somepros:"old"}]
];
And we have nestedObj like
let obj ={
"a":{
"count":2
},
"b":{
"count":2
},
"c":{
"count":1
},
"e":{
"count":1
}
};
Now What I want is basically Using nested object i want to check the array's of object's array value if it exist or not and want to create an array as decleared above. Here the count in object is number no.of times the Array of object will appear in above array but. Suppose count is 2 for object proprerty "a" there is already an array of object exist having value "a". i want another array to be pushed number of time's the count but already exist 1 so 1 more time i will add it.
What I need is from Obj:
NewArr =[
[{value:'a',somepros:"old"}],
[{value:'a',somepros:"newpushed"}],
[{value:'b',somepros:"old"}],
[{value:'b',somepros:"newpushed"}],
[{value:'c',somepros:"newpushed"}],
[{value:'e',somepros:"newpushed"}],
];

The question doesn't really seems to make much sense in my opinion, but here it is:
let array = [
[{value:'a',somepros:"old"}],
[{value:'d',somepros:"old"}],
[{value:'b',somepros:"old"}]
],
obj ={
"a":{
"count":2
},
"b":{
"count":2
},
"c":{
"count":1
},
"e":{
"count":1
}
};
const res = [];
// loop each entry from obj.
for (const [key, {count}] of Object.entries(obj)) {
// check whether the key exists in the original array.
const matched = array.find((arr) => arr[0].value === key);
// If it exists, push it.
if (matched) res.push(matched);
// then, add X elements "newpushed", where X is given by the count declared - 0 if matched doesn't exist, otherwise 1 (since an element already existed).
res.push(
...Array.from({length: (count - (matched ? 1 : 0))}, (_) => ([{ value: key, somepros: 'newpushed' }]))
);
}
console.log(res);
Comments in the snippet explains what is done.

Related

How to change the object key from nested array object and return array object

I have an array arr1 and an object arr2 with a nested config array.
If the object of arr1 has a key that matches with an id in that nested config and deeper questions array, then change that key (in the arr1 object) with the title property that is found next to that id.
Here is an example. The key isWorking from arr1 is the same as arr2.config[0].questions[0].id value, so
change that isWorking key to the value found in arr2.config[0].questions[0].custom.title.
var arr1= [
{"jobs": "Marketing","isWorking": yes,"country": "MY"},
{"country": "IN","members": 4}
]
var arr2=
{
"id":1,
"name":"xxx",
"config":[
{
"questions":[
{
"id":"isWorking",
"custom":{
"title":"Are you working?"
}
},
{
"id":"jobs",
"custom":{
"title":"Please specify job(s)"
}
}
]
},
{
"questions":[
{
"id":"country",
"custom":{
"title":"which Country?"
}
},
{
"id":"members",
"type":"choices",
"custom":{
"title":"How many members?"
}
}
]
}
]
}
Expected output:
[
{"Please specify job(s)": "Marketing","Are you working": yes,"which Country": "MY"},
{"which Country": "IN","How many members": 4}
]
I tried:
var result = arr1.map(e => ({
arr2.config.find(i => {
i.questions.find( q => {
q.id === Object.key(e) ? Object.key(e) === q.custom.title : q.id
}
})
}))
In your code the find callbacks do not return anything. When you have a code block (with braces) you need a return statement. Also, the outer object literal which you have as the return value of the map callback cannot have just the find call in it. It should have the proper object literal syntax, like with spread syntax. Moreover, the find method can only return an existing object, not a new, modified one.
I will assume here that the matching strings for the first object have to be found in the first questions array, and for the second object in the second questions array.
I also propose to rename arr2, because it isn't an array. It is a plain object, with a property that is an array (config).
Here is how you could do it with Object.fromEntries and Object.entries:
const arr1 = [{"jobs": "Marketing","isWorking": "yes","country": "MY"}, {"country": "IN","members": 4}];
const obj = {"id":1,"name":"xxx","config":[{"questions":[{"id":"isWorking","custom":{"title":"Are you working?"}},{"id":"jobs","custom":{"title":"Please specify job(s)"}}]},{"questions":[{"id":"country","custom":{"title":"which Country?"}},{"id":"members","type":"choices","custom":{"title":"How many members?"}}]}]}
const result = arr1.map((e, i) => Object.fromEntries(
Object.entries(e).map(([key, value]) =>
[obj.config[i].questions.find(({id}) =>
key === id
)?.custom?.title ?? key, value]
)
))
console.log(result);

How to convert JSON Object into key value pair in JS? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
{"1":"val1","2":"val2","3":"val3"}
i want it to converted like this:
{"Id":"1","value":"val1","Id":"2","value":"val2","Id":"3","value":"val3"}
little Help Please would be much appricated
You can't use the same key name in one object.
instead you can do this.
const origin = {"1":"val1","2":"val2","3":"val3"}
const converted = Object.entries(origin).map( ([key,value]) => ({id: key, value }) );
console.log(converted);
What you have posted is invalid.
What you might want is:
const object = {"1":"val1","2":"val2","3":"val3"};
console.log(Object.entries(object));
// or
console.log(Object.keys(object).map(i => ({Id: i, value: object[i]})));
You could use a loop over Object.entries.
E.g. something like:
const newObjArr = [];
for(let [key, value] of Object.entries(obj)){
newObj.push({Id: key, value});
}
The above would return an array of objects, but I'm sure you can amend it to your particular use case.
const data = {"1":"val1","2":"val2","3":"val3"};
const result = Object.keys(data).map((key) => ({ id: key, value: data[key] }));
The result will be [{ id: "1", value: "val1" }, { id: "2", value: "val2" }, { id: "3", value: "val3" }]
As pointed out this is invalis. If you want to convert it if would look like this:
[{"Id":"1","value":"val1"},{"Id":"2","value":"val2"},{"Id":"3","value":"val3"}]
You can make an function that converts this.
const object = {"1":"val1","2":"val2","3":"val3"};
console.log(Convert(object));
function Convert(obj){
return Object.keys(obj).map(i => ({Id: i, value: obj[i]}));
}
You cannot do this. Object is a unique key value pair.
{"Id":"1","value":"val1","Id":"2","value":"val2","Id":"3","value":"val3"}
Suppose you want to merge two object and What if both the object has same key, it simply merge the last objects value and have only one key value.
You can convert your large object to several small objects and store them in an array as this snippet shows. (It could be much shorter, but this verbose demo should be easier to understand.)
// Defines a single object with several properties
const originalObject = { "1" : "val1", "2" : "val2", "3" : "val3" }
// Defines an empty array where we can add small objects
const destinationArray = [];
// Object.entries gives us an array of "entries", which are length-2 arrays
const entries = Object.entries(originalObject);
// `for...of` loops through an array
for(let currentEntry of entries){
// Each "entry" is an array with two elements
const theKey = currentEntry[0]; // First element is the key
const theValue = currentEntry[1]; // Second element is the value
// Uses the two elements as values in a new object
const smallObject = { id: theKey, value: theValue };
// Adds the new object to our array
destinationArray.push(smallObject);
} // End of for loop (reiterates if there are more entries)
// Prints completed array of small objects to the browser console
console.log(destinationArray);
const obj = {"1":"val1","2":"val2","3":"val3"}
const newObject = Object.keys(obj).map(e => {
return {ID: e , value : obj[e] }
});
console.log(newObject); // [ { ID: '1', value: 'val1' },
{ ID: '2', value: 'val2' },
{ ID: '3', value: 'val3' } ]
it will give u an array of object, later u need to convert it to object and flat the object:
How do I convert array of Objects into one Object in JavaScript?
how to convert this nested object into a flat object?

Javascript - how to loop through dict inside a list

So I am pretty new when it comes to Javascript and it is as simple as read a json list with a value of:
{
"URL": [{
"https://testing.com/en/p/-12332423/": "999"
}, {
"https://testing.com/en/p/-123456/": "123"
},
{
"https://testing.com/en/p/-456436346/": "422"
}
]
}
What I would like to do is to have both the URL and the amount of numbers etc
"https://testing.com/en/p/-12332423/" and "999"
and I would like to for loop so it runs each "site" one by one so the first loop should be
"https://testing.com/en/p/-12332423/" and "999"
second loop should be:
"https://testing.com/en/p/-123456/" and "123"
and so on depending on whats inside the json basically.
So my question is how am I able to loop it so I can use those values for each loop?
As Adam Orlov pointed out in the coment, Object.entries() can be very useful here.
const URLobj = {
"URL": [{
"https://testing.com/en/p/-12332423/": "999"
}, {
"https://testing.com/en/p/-123456/": "123"
},
{
"https://testing.com/en/p/-456436346/": "422"
}
]
};
URLobj.URL.forEach(ob => {
console.log('ob', ob);
const entries = Object.entries(ob)[0]; // 0 just means the first key-value pair, but because each object has only one we can just use the first one
const url = entries[0];
const number = entries[1];
console.log('url', url);
console.log('number', number);
})
You mean something like this using Object.entries
const data = {
"URL": [
{"https://testing.com/en/p/-12332423/": "999"},
{"https://testing.com/en/p/-123456/": "123"},
{"https://testing.com/en/p/-456436346/": "422"}
]
}
data.URL.forEach(obj => { // loop
const [url, num] = Object.entries(obj)[0]; // grab the key and value from each entry - note the [0]
console.log("Url",url,"Number", num); // do something with them
})
let's call your object o1 for simplicity. So you can really go to town with this link - https://zellwk.com/blog/looping-through-js-objects/
or you can just use this code :
for(var i = 0; i < o1.URL.length; i++) {
//each entry
var site = Object.keys(URL[i]) [0];
var value = Object.values(URL[i]) [0];
// ... do whatever
}
don't forget each member of the array is an object (key : value) in its own right
You can extract the keys and their values into another object array using map
Then use the for loop on the newly created array. You can use this method on any object to separate their keys and values into another object array.
const data = {
"URL": [{
"https://testing.com/en/p/-12332423/": "999"
}, {
"https://testing.com/en/p/-123456/": "123"
},
{
"https://testing.com/en/p/-456436346/": "422"
}
]
}
var extracted = data.URL.map(e => ({
url: Object.keys(e)[0],
number: Object.values(e)[0]
}))
extracted.forEach((e) => console.log(e))

How to remove the repeating `place` name which contains the same `name`?

I find the following answer help me a lot in removing duplicate object array which contains duplicates.
I've made a fork of the example which I modified.
The function related:
const uniqueArray = things.thing.filter((thing,index) => {
return index === things.thing.findIndex(obj => {
return JSON.stringify(obj) === JSON.stringify(thing);
});
});
For example I have:
[
{"place":"here","name":"stuff"},
{"place":"there","name":"morestuff"},
{"place":"there","name":"morestuff"},
{"place":"herehere","name":"stuff"}
]
It would return:
[
{"place":"here","name":"stuff"},
{"place":"there","name":"morestuff"},
{"place":"herehere","name":"stuff"}
]
How to remove the repeating place name which contains the same name?
Expected output:
[
{"place":"here","name":"stuff"},
{"place":"there","name":"morestuff"}
]
You can reduce over the array of objects. Simply, if an object with a key value the same as the current object already exists in the accumulator, don't add it again.
Here's a function that allows you specify which key you want to dedupe:
const arr = [
{"place":"here","name":"stuff"},
{"place":"there","name":"morestuff"},
{"place":"there","name":"morestuff"},
{"place":"herehere","name":"stuff"}
];
// Accepts an array and a key that should have the
// duplicates removed
function remove(arr, key) {
// Iterate over the array passing in the accumulator
// and the current element
return arr.reduce((acc, c) => {
// If there is an object in the accumulator with the
// same key value as the current element simply return the
// accumulator
if (acc.find(obj => obj[key] === c[key])) return acc;
// Otherwise add the current element to the accumulator
// and return it
return acc.concat(c);
}, []);
}
function showJSON(arr, id) {
const json = JSON.stringify(arr, null, 2);
document.querySelector(`#${id} code`).textContent = json;
}
// remove duplicate places
showJSON(remove(arr, 'place'), 'places');
// remove duplicate names
showJSON(remove(arr, 'name'), 'names');
<div id="places">
Removed duplicate places
<pre><code></code></pre>
</div>
<div id="names">
Removed duplicate names
<pre><code></code></pre>
</div>
Check this
const things = [
{"place":"here","name":"stuff"},
{"place":"there","name":"morestuff"},
{"place":"there","name":"morestuff"},
{"place":"herehere","name":"stuff"}
]
const uniqueArray = things.reduce((accumulator, currentValue) => {
if (accumulator.find(a => a.name === currentValue.name))
return accumulator;
else
return (accumulator.push(currentValue), accumulator);
}, []);
Output
[ { place: 'here', name: 'stuff' },
{ place: 'there', name: 'morestuff' } ]
You can use array reduce with filter
let data=[
{"place":"here","name":"stuff"},
{"place":"there","name":"morestuff"},
{"place":"there","name":"morestuff"},
{"place":"herehere","name":"stuff"}
]
// Using reduce() to separate the contents we want
let result=data.reduce((acc,value)=>{
if(acc.filter(val=>val.name==value.name).length==0) // checking the accumulator if it already containsa the value
{
acc.push(value); // if the array returned is of length==0 we can push in it
}
return acc;
},[])
console.log(result);
See Array Filter, Array.prototype.Reduce

Optimal way to convert an Array of Objects into an Array of Arrays containing Objects

Take for example this extremely simplified Array of Objects:
[
{
createID: '1'
// Many other properties...
},
{
createID: '1'
// Many other properties...
},
{
createID: '1'
// Many other properties...
},
{
createID: '37'
// Many other properties...
},
{
createID: '37'
// Many other properties...
},
{
createID: '2'
// Many other properties...
},
{
createID: '2'
// Many other properties...
},
{
createID: '14'
// Many other properties...
},
];
Given this Array I then use the objects createID property to create an Array of Arrays containing Objects [[{..},{..}], [{..}], ..n]. This final format is required by the current front end framework I am using (Angular v6).
To accomplish this task I use the following code, where tempArr is an array like the example array provided above.
let currentGroup: string = tempArr[0].createID;
let tempGrouped: any[] = [];
let childGroup: any[] = [];
tempArr.forEach(item => {
if (item.createID !== currentGroup) {
tempGrouped.push(childGroup);
childGroup = [];
currentGroup = item.createID;
}
childGroup.push(item);
});
tempGrouped.push(childGroup);
This code works fine. However, I can't help but believe there must be a more efficient and elegant way given the data to convert an Array of objects into an Array of Arrays containing objects.
UpdateIt is important to note that the createID's are only id's that signify which objects should be grouped together. Therefore, they do not need to be numerically ordered by createID. In addition, the objects do come from the server "grouped" with their sibling objects (same createID) as you can see in the given example array provided.
Your example has all identical IDs adjacent to each other. If that is guaranteed to always be the case, looping though and pushing to a new array is all you need. However if this isn't the case, your solution will fail to group items properly. In that case using a hash table will allow you to still group by ID with same asymptotic complexity.
You can group your objects into a hash table object with keys created from createdID. This will let you group everything efficiently. Then just take the objects from the hash table:
let arr = [{createID: '1'},{createID: '1'},{createID: '1'},{createID: '37'},{createID: '37'},{createID: '2'},{createID: '2'},{createID: '14'},];
let o = arr.reduce((a, c) => {
(a[c.createID] || (a[c.createID] = [])).push(c)
return a
}, {} )
// o is a an object with createID keys pointing to arrays of grouped objects
// just take the values
console.log(Object.values(o))
Edit based on question edit
Since the objects will already be grouped, there's not a better way than looping through. If you want an option that doesn't add the temp arrays, you can still use reduce(), which is essentially the same as your current solution, but maybe a little more self contained:
let tempArr = [{createID: '1'},{createID: '1'},{createID: '1'},{createID: '37'},{createID: '37'},{createID: '2'},{createID: '2'},{createID: '14'},];
let r = tempArr.reduce((a, c, i, self) => {
if (i === 0 || self[i-1].createID !== c.createID)
a.push([])
a[a.length - 1].push(c)
return a
}, [])
console.log(r)
Assuming that your array of data is stored into a variable called data:
const result = data.reduce((acc, current) => {
if (!acc.dictionary[current.createID]) {
const createIdArray = [];
acc.dictionary[current.createID] = createIdArray;
acc.array.push(createIdArray);
}
acc.dictionary[current.createID].push(current);
return acc;
}, {array: [], dictionary: {}}).array;
This way, you'll loop only once on data, and it's efficient as we don't use filter or find (which would go through the whole array again and again).
Here's the output:
[
[
{
createID: '1',
},
{
createID: '1',
},
{
createID: '1',
},
],
[
{
createID: '37',
},
{
createID: '37',
},
],
[
{
createID: '2',
},
{
createID: '2',
},
],
[
{
createID: '14',
},
],
];
Here's a running demo: https://stackblitz.com/edit/typescript-phbzug
Summary:
The dictionary is self contained within the reduce function which means that as soon as the reduce is done, it'll be garbage collected
Not relying on any external variables, easier to reason about and IMO a better practice
This solution is more robust (the array doesn't need to be sorted) for ~ the same number of lines as OP's answer
Clean: With the dictionary you know directly what you're accessing and it's really fast
you want to group by createID?
let grouped=tempArray
//first get uniq values
.filter((s,index)=>tempArray.findIndex(f=>f.createID==s.createID)==index)
//then, with the uniq values make a map
.map(seg=>{ //with each uniq value, create an object with two properties
return {
createID:seg.createID, //the key
items:tempArray.filter(s=>s.createID==seg.createID) //An array with the values
}
})

Categories