Merging the contents of my array into one object - javascript

I have an array of several objects
array1 =[ {1:Eat},{2:Shower},{3:Shave}]
I want to convert this array into a single object
object1 ={1:Eat, 2:Shower, 3:Shave}
How do I go about it. The keys(1,2,3) are unique

THE SOLUTION
array.reduce((a, v) => Object.assign(a,v), {})
THE EXPLANATION
Array.reduce() loops throw the initial array aimed to "reduce" it into a single object. The reduce method allows you to store the return value of each of your iterations. It requires an initial value which in this case it will be the empty object {} that we will be filling up with our array.
Then we use Object.assign(target, source) which concatenates two objects together returning the concatenated object which in this case it will saved into our accumulator and be used as a target for the next iteration giving you when it finishes the constructed final object. As you have objects as the keys of the array, each single property Object(source) will be "assigned" to a master one (target) that will be collecting all of them into one.
array1 =[ {1:'Eat'},{2:'Shower'},{3:'Shave'}]
obj1 = array1.reduce((a, v) => Object.assign(a,v), {})
console.log(obj1)

The easiest way to achieve this is to reduce the list of objects into a single object.
const
input = [{ 1: 'Eat' }, { 2: 'Shower' }, { 3: 'Shave' }],
output = input.reduce((acc, obj) => ({ ...acc, ...obj }), {});
console.log(output);
.as-console-wrapper { top: 0; max-height: 100% !important; }

fromEntries and a flatMap seems to do the trick nicely
const array1 = [ {1:'Eat'},{2:'Shower'},{3:'Shave'}]
const obj1 = Object.fromEntries(array1.flatMap(item => Object.entries(item)))
console.log(obj1)

You could simply loop through the array and each object within it and add it to a master object as shown below.
const array1 =[{ 1: 'Eat' }, { 2: 'Shower' }, { 3: 'Shave' }];
const masterObj = {};
array1.forEach(obj => {
for (const property in obj) {
masterObj[property] = obj[property];
};
});
console.log(masterObj);

I'm not sure if my method of using Object.keys() and Object.values() is the most efficient method, but it's something to get you started:
array1 = [{
1: "Eat"
}, {
2: "Shower"
}, {
3: "Shave"
}];
object1 = {};
array1.forEach(v => {
object1[Object.keys(v)[0]] = Object.values(v)[0];
});
console.log(object1);

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);

Can destructuring an array be used to map properties of each elements?

Suppose there is an array like this:
const a = [ {p:1}, {p:2}, {p:3} ];
Is it possible to destructure this array in order to obtain p = [1, 2, 3] ?
Because this does not work :
const [ ...{ p } ] = a; // no error, same as const p = a.p;
// p = undefined;
Edit
In response to all the answers saying that I need to use Array.prototype.map, I am aware of this. I was simply wondering if there was a way to map during the destructuring process, and the answer is : no, I need to destructure the array itself, then use map as a separate step.
For example:
const data = {
id: 123,
name: 'John',
attributes: [{ id:300, label:'attrA' }, { id:301, label:'attrB' }]
};
function format(data) {
const { id, name, attributes } = data;
const attr = attributes.map(({ label }) => label);
return { id, name, attr };
}
console.log( format(data) };
// { id:123, name:'John', attr:['attrA', 'attrB'] }
I was simply wondering if there was a way, directly during destructuring, without using map (and, respectfully, without the bloated lodash library), to retrive all label properties into an array of strings.
Honestly I think that what you are looking for doesn't exist, normally you would map the array to create a new array using values from properties. In this specific case it would be like this
const p = a.map(element => element.p)
Of course, there are some packages that have many utilities to help, like Lodash's map function with the 'property' iteratee
you can destructure the first item like this :
const [{ p }] = a;
but for getting all values you need to use .map
and the simplest way might be this :
const val = a.map(({p}) => p)
Here's a generalized solution that groups all properties into arrays, letting you destructure any property:
const group = (array) => array.reduce((acc,obj) => {
for(let [key,val] of Object.entries(obj)){
acc[key] ||= [];
acc[key].push(val)
}
return acc
}, {})
const ar = [ {p:1}, {p:2}, {p:3} ];
const {p} = group(ar)
console.log(p)
const ar2 = [{a:2,b:1},{a:5,b:4}, {c:1}]
const {a,b,c} = group(ar2)
console.log(a,b,c)

JS find array of String and Array Object without duplicates

I had a lists of duplicate array of String and array of object. I want to find the property into one particular object of array uniquely without duplication of array object.
If can done in lodash library, it would be awesome.
const arr1 = ['test#email', 'test2#email']
const arr2 = [{ id: 1, email: 'test#email' }]
Expected result
['test2#email']
this is what I done so far
By turning arr1 into object frist so I can compare with arr2
const emailLists = _.map(arr, function (item) {
console.log(item)
return { email: item }
})
then merge them to together and used uniq to remove duplicates
const merge = _.unionBy(array1, array2, 'email')
const result _.uniq(merge, 'email');
I think it still not a good process and not clean
You can do it without lodash
const arr1 = ['test#email', 'test2#email']
const arr2 = [{ id: 1, email: 'test#email' }]
const emailToDelete = arr2.map(a => a.email)
const result = arr1.filter(e => !emailToDelete.includes(e))
console.log(result)
You can use lodash chain to solve that:
const result = _([...arr1, ...arr2.map(i => i.email)]) // ['test#email', 'test2#email', 'test#email']
.countBy() // { test#email: 2, test2#email: 1 }
.pickBy(count => count === 1) // { test2#email: 1 }
.keys() // ['test2#email']
.value();
You can use filter on the first array and check that an email address matches with some of your objects in the second array. So even if it matches with multiple objects, the matching email will only be in the output once.
I want to find the property into one particular object of array uniquely without duplication of array object
So then your expected output is wrong, as you provide an email that is not found in the object array. I guess that was a typo in your question.
const arr1 = ['test#email', 'test2#email']
const arr2 = [{ id: 1, email: 'test#email' }]
const result = arr1.filter(search => arr2.some(({email}) => email == search));
console.log(result);

How to get property of an object

I'm creating an empty array and fill it with object.
export const model = [
{isMine: false},
]
const newArr = Array(25);
newArr.fill(model);
newArr.forEach((item) => {
console.log(item);
})
This logs out all objects with the array. But I don't know how to log out the isMine property... I always get undefined
I hope this is what you need. If you spread (...) the model it will get stored as objects. But if you don't spread it will be stored as an array inside an array which contain an object
const model = [
{isMine: false},
]
const newArr = Array(25).fill(...model);
newArr.forEach((item) => {
console.log(item.isMine);
})
I hope this helps, you need to access array inside array
const model = [
{isMine: false},
];
console.log(model[0].isMine);
const newArr = Array(25);
newArr.fill(model);
console.log(newArr);
newArr.forEach(x => x.forEach(y => console.log(y.isMine)));
newArr is a 2 dimensional array, since model is an array.
So to access the property isMine in your forEach loop you'd do:
newArr.forEach((item) => {
// item is an array, so get the value at the first index
console.log(item[0].isMine);
})

Get array of keys based on values from another array

Say I have an array of objects that looks like this
let myArray = [
{item1: true},
{item2: false},
{item3: true},
{item4: false}
]
How would I iterate though this to return a new array of true values that looks like this:
let newArray = ['item1', 'item3']
I found this function but it only returns single items:
function findKey(map, term) {
var found = [];
for(var property in map) {
if(map.hasOwnProperty(property)) {
for(var key in map[property]) {
if(map[property].hasOwnProperty(key) && key === term) {
found.push(property);
}
}
}
}
return found;
}
Assuming myArray always contains objects with only 1 property.
let newArray = myArray
.map(item => Object.entries(item)[0])
.filter(([key, value]) => value)
.map(([key, value]) => key)
You could access the first key of each array item via Object.keys(), and use this to filter items with a true value for that first key, and then complete the process with a call to map() to transform the item to a value based on the same "first key" technique:
let myArray = [
{item1: true},
{item2: false},
{item3: true},
{item4: false}
]
let result = myArray
.filter(item => item[ Object.keys(item)[0] ] === true)
.map(item => Object.keys(item)[0])
console.log(result)
Use the function reduce to build the desired output. The handler of the function reduce will get the keys and check for each value === true.
This approach checks for the whole set of keys within an object. Further, this way you only use one loop.
let myArray = [{item1: true},{item2: false},{item3: true},{item4: false}],
result = myArray.reduce((a, c) => a.concat(Object.keys(c).filter(k => c[k] === true)), []);
console.log(result);
Something much optimized than the accepted answer would look like this:
const arr = [
{ item1: true },
{ item2: false },
{ item3: true },
{ item4: false }
]
const result = [];
const len = arr.length;
for (let i = 0; i < len; ++i) {
const obj = arr[i];
const key = Object.keys(obj)[0];
if(obj[key]) {
result.push(key);
}
}
console.log(result);
There is only one loop over the array, instead of map and filter which ends up looping twice.
Shortest
let newArray = myArray.map( x=>Object.keys(x)[0] ).filter( (k,i)=>myArray[i][k] );
In above solution first we use: map which works as for-loop to get array of keys (using Object.keys) ["item1", "item2", "item3", "item4"]. Then we filter that array by choose only those keys for which original array object has true. e.g myArray[0]["item1"] -> true (we use fact that filter funtion takes array element (k) and its index (i) which is the same for elements in myArray). In map and filter we use arrow functions.

Categories