I have an array :
[
"2022-05-20",
"2022- 06-22",
"2022-06-20"
]
and I want to produce an object like this:
{
'2022-05-20': {disabled:true},
'2022-06-22': {disabled: true},
'2022-06-20': {disabled: true},
}
I tried using a for loop but it kept producing errors. Is this possible with javascript?
You can use Array#reduce as in the following demo. You can also use Array#map but you would have to use Object.fromEntries as well.
const input = [ "2022-05-20", "2022- 06-22", "2022-06-20" ],
output = input.reduce(
(prev,cur) =>
({...prev,[cur]:{disabled:true}}), {}
);
console.log( output );
USING Array#map ...
Here is how you can use Array#map:
const input = [ "2022-05-20", "2022- 06-22", "2022-06-20" ],
output = Object.fromEntries(
input.map(date => [date, {disabled:true}])
);
console.log( output );
Can do it:
let dates = [
"2022-05-20",
"2022- 06-22",
"2022-06-20"
];
let newObj = Object.assign(...dates.map(key => ({[key]: {disabled: true}})));
console.log(newObj)
This might get the job done.
const yourArray = ["2022-05-20", "2022-06-22", "2022-06-20"];
const obj = {};
for(const x of yourArray) obj[String(x)] = { disabled: true };
console.log(obj); // :)
Create the variable obj that is going to save the produced object you want. Iterating throw your array and using a string parsed version of the value in the current iteration (parsing just in case, if you already know the array is made of strings, this is kinda unnecessary) to save it as a key on the new object, also assigning to that key, the value { disabled: true }.
Here is a one liner solution:
let res = data.reduce((acc, curr) =>(acc[curr] = {disabled: true}, acc), {});
Related
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)
I'm trying to convert the methods part of an Express Router into a one-dimensional array of uppercase string words, so this:
layer.route.methods: { get: true, post: true }
into:
methods: ["GET", "POST"]
This is what I came up with, but isn't there a more subtle way?
const methods = [];
!layer.route.methods.get || methods.push('GET');
!layer.route.methods.post || methods.push('POST');
This can be achieved with a combination of filter (to get only the methods with true) and map (to capitalize).
const methods = { get: true, post: true };
const result = Object.keys(methods).filter(method => methods[method]).map(method => method.toUpperCase());
console.log(result);
Turn down object to an array by using Object.keys(object) and then use loop either for or map to iterate and check if item exist in that converted array convert then to uppercase using item.toUpperCase()
One of the ways is to use reducer, to filter and modify values in one iteration.
const inputObject = { get: true, post: true };
const methods = Object.entries(inputObject).reduce(
(accumulator, [key, value]) => {
if (value) accumulator.push(key.toUpperCase());
return accumulator;
},
[]
);
console.log(methods);
I have an JSON object like
datas = [
{"id":1,"name":"Test","age":24},
{"id":2,"name":"Test1","age": 30}
]
I want to modify the JSON object like below
datas = [
{"1":{"name":"Test","age":24}},
{"2":{"name":"Test1","age": 30}}
]
I want to do the same using lodash . I can understand map over the data and create a new object should fix this
updated_data=[]
_.map datas, (data) ->
Obj = {}
Obj[data.id] = data
updated_data.push(Obj)
But I am looking for lodash way of achieving the same .
Use Array.map() (or _.map()) with destructuring and object rest (...):
const datas = [{"id":1,"name":"Test","age":24}, {"id":2,"name":"Test1","age": 30}]
const result = datas.map(({ id, ...o }) => ({ [id]: o }))
console.log(result)
With lodash you can do the same, but instead of destructuring use _.omit() to remove the id from the original object, and use _.zipObject() combine it with the id:
const datas = [{"id":1,"name":"Test","age":24}, {"id":2,"name":"Test1","age": 30}]
const result = _.map(datas, o => _.zipObject([o.id], [ _.omit(o, 'id')]))
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js" integrity="sha512-WFN04846sdKMIP5LKNphMaWzU7YpMyCU245etK3g/2ARYbPK9Ub18eG+ljU96qKRCWh+quCY7yefSmlkQw1ANQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
I think you don't need to use an extra library for this. This way you can achieve the desired result:
datas.map((item) => {
const { id, ...rest } = item;
return {
id: rest,
};
});
Is there a one-line way to transform array value to the properties name of an object?
Example:
var arr = ['name', 'age', 'size'];
To
{'name' :null, 'age':null, 'size':null}
Actually I'm processing like this:
var arr = ['name', 'age', 'size'];
let obj = {};
arr.map(z => obj[z] = null);
I suppose that is the shortest way but I'm not sure.
Use reduce:
arr.reduce((prev, curr) => {
return Object.assign(prev, {[curr]: null})
}, {})
or you can one-line it if you want, but imo it looks worse then:
arr.reduce((prev, curr) => Object.assign(prev, {[curr]: null}), {})
Note, that Object.assign is a better way to code this, rather than using spread operator ({... }).
Spread operator creates a NEW object every loop. This can lead to big performance issues.
Object.assign on the other hand works on the first object.
reduce could turn it into a one-liner:
var obj = arr.reduce((acc, curr)=> ({...acc, [curr]: null}),{})
You can use Array.prototype.reduce method to convert an array to another type
var arr = ["name", "age", "size"];
let output = arr.reduce((accumulator, current) => {
return {...accumulator, [current]: null}
}, {})
console.log(output);
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.