Make new object array from object in javascript [duplicate] - javascript

This question already has answers here:
Convert object to an array of objects?
(5 answers)
Closed 2 years ago.
i have object like:
let obj = {
type: 1
name: 'Test'
pr: 0
g: 1
}
and i wan't to make like this object with it:
obj = [
{
title: "type",
value: 1,
},
{
title: "name",
value: "Test",
},
{
title: "pr",
value: 0,
},
{ title: "gr", value: 1 },
];
so basically first key will be in name and second key will be value.
What i tried?
newObj = Object.keys(obj).forEach(function (key) {
obj = {
name: key,
value: key,
};
});
it's worked but it's give just first 2 value of the object and not makes object array.
so output is :
obj = {
name: type,
value: 1,
};
another entries not visible.
What i need to do ?

You can use Object.entries:
const obj = {
type: 1,
name: 'Test',
pr: 0,
g: 1
};
const res = Object.entries(obj)
.map(([title, value]) => ({title, value}));
console.log(res);
If you're not familiar with this syntax:
([title, value]) => ({title, value})
It could be rewritten as:
function (x) { return { title: x[0], value: x[1] }; }
But in the above example, I used a destructuring assignment to create 2 variables title and value from the provided key/value pair.
And {title, value} is just a shorthand syntax for { title: title, value: value }.

You can use Object.keys(...) and use map to get your desired result like below.
Object.keys(obj).map(x => ({ title: x, value: obj[x] }));
const obj = {
type: 1,
name: 'Test',
pr: 0,
g: 1
};
const res = Object.keys(obj).map(x => ({ title: x, value: obj[x] }));
console.log(res);

Also you can do this by reduce method with Object.keys(), as an alternative:
let obj = {
type: 1,
name: 'Test',
pr: 0,
g: 1,
}
const result = Object.keys(obj).reduce((acc, rec) => {
return [...acc, {
title: rec,
value: obj[rec]
}]
}, [])
console.log(result);

Related

How to merge 2 Arrays with nested Objects into 1 array without duplicates

I have two arrays of objects like this:
const oldArr = [
{ 'Tomorrow': [{ id: 2 }, { id: 4 }, { id: 3 }] },
{ 'Saturday': [{ id: 2 }, { id: 4 }, { id: 3 }] }
]
const newArr = [
{ 'Monday': [{ id: 2 },{ id: 4},{ id: 3 }] },
{ 'Tomorrow': [{ id: 1 },{ id: 5 }]}
]
I want to merge both without any duplicate keys, so it should result in:
[
{ 'Tomorrow': [{ id: 2 }, { id: 4 }, { id: 3 }, { id: 1 }, { id: 5 }] },
{ 'Saturday': [{ id: 2 }, { id: 4 }, { id: 3 }] },
{ 'Monday': [{ id: 2 }, { id: 4 }, { id: 3 }] }
]
As you can see, the contents of Tomorrow have been added to the original Tomorrow, and the object of Monday has been added on.
I've vaguely figured out how to do so with nested loops, but I'm guessing there is a simpler solution using map, reduce, or the like.
This can be easily accomplished with a combination of the neat javascript spread syntax, Array and Object prototype functions, and destructuring patterns.
[...oldArr, ...newArr].flatMap(Object.entries).reduce(
(acc, [k, v]) => ({ ...acc, [k]: [...acc[k]||[], ...v] }), {})
As simple as this!
const oldArr = [
{'Tomorrow': [{'id':2},{'id':4},{'id':3}]},
{'Saturday': [{'id':2},{'id':4},{'id':3}]}
]
const newArr = [
{'Monday': [{'id':2},{'id':4},{'id': 3}]},
{'Tomorrow': [{'id':1},{'id':5}]}
]
const result = [...oldArr, ...newArr].flatMap(Object.entries).reduce(
(acc, [k, v]) => ({ ...acc, [k]: [...acc[k]||[], ...v] }), {})
console.log(result)
For a very detailed explanation of how this works, refer to this extended answer to a similar question. The difference in that other question is that there, each inner object had only one object as a value, instead of an array.
This can be achieved by iterating the combined arrays to generate an object with all the values for each key in the arrays; then using Object.entries to map that back to the original format:
const oldArr = [
{'Tomorrow': [{'id':2},{'id':4},{'id':3}]},
{'Saturday': [{'id':2},{'id':4},{'id':3}]}
]
const newArr = [
{'Monday': [{'id':2},{'id':4},{'id': 3}]},
{'Tomorrow': [{'id':1},{'id':5}]}
]
const result = Object.entries(oldArr.concat(newArr)
.reduce((a, o) => {
let k = Object.keys(o)[0]
a[k] = (a[k] || []).concat(o[k])
return a
}, {})
).map(([k, v]) => ({ [k] : v}))
console.log(result)

How to merge 2 objects into one - javascript

I need help with solution on this. I have two objects:
Input:
obj1 = [{name:A}, {name:B}, {name:C}...,]
obj2 = [{value:1}, {value:2}, {value:3}...,]
And i need to make from these 2 objects one.
Output:
obj3 = [{A:1}, {B:2}, {C:3}...,]
Anybody know how to merge obj and obj2 to one? Thanks!
If you have consitent nameing, you could map with index.
const
names = [{ name: 'A' }, { name: 'B' }, { name: 'C' }],
values = [{ value: 1 }, { value: 2 }, { value: 3 }],
result = names.map(({ name }, i) => ({ [name]: values[i].value }));
console.log(result);
You could do this
const obj1 = [{name:'A'}, {name:'B'}, {name:'C'}];
const obj2 = [{value:1}, {value:2}, {value:3}];
const merged = Array.from({length:Math.min(obj1.length, obj2.length)}, (_,i) => {
return { [obj1[i].name]: obj2[i].value };
});
console.log(merged);

JavaScript Equivalent to C# LINQ or another way to fetch data [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 2 years ago.
Improve this question
I have the JS array something like that
var arr = [{
TimeEdit: "2020-10-29T10:45:00.21Z",
Date: "2020-10-29T00:00:00",
Parameters: [ { Id: 1, Value: 1}, { Id: 2, Value: 348 }]
},{
TimeEdit: "2020-10-29T10:43:52.22Z",
Date: "2020-10-29T00:00:00",
Parameters: [ { Id: 1, Value: 12}, { Id: 2, Value: 348 }]
},{
TimeEdit: "2020-10-30T10:47:12.33Z",
Date: "2020-10-30T00:00:00",
Parameters: [ { Id: 1, Value: 3}, { Id: 2, Value: 2 }]
}];
and I want to select from this array data with a unique "Date" sorted by "TimeEdit" so that at the output I can get this array
[{
TimeEdit: "2020-10-29T10:45:00.21Z",
Date: "2020-10-29T00:00:00",
Parameters: [ { Id: 1, Value: 1}, { Id: 2, Value: 348 }]
},{
TimeEdit: "2020-10-30T10:47:12.33Z",
Date: "2020-10-30T00:00:00",
Parameters: [ { Id: 1, Value: 3}, { Id: 2, Value: 2 }]
}];
In C# code I would do something like that:
var dates = arr.Select(r => r.Date).Distinct().ToList();
foreach (var date in dates)
{
WorkLog log = arr.Where(r => r.Datetime == date).OrderByDescending(r => r.TimeEdit).FirstOrDefault();
//to do some stuff here
}
So what is the best way to do so in JS?
JavaScript has a number of built-in functions that help you in working with arrays in a linq-ish way. Functions like map (equivalent of Select) and filter (equivalent of Where) come to mind. Check out MDN for docs.
Even though these can be very useful, it can be useful to use another library for working with arrays or objects. From my experience lodash is very handy for manipulating arrays. It has a chain method that you can use to express operations in a very linq-ish way.
const dates = _.chain(arr).map(r => r.Date).uniq().value();
dates.forEach(date => {
const log = _.chain(arr)
.filter(r => r.Datetime === date)
.sortBy(r => r.TimeEdit)
.reverse()
.head();
//to do some stuff here
});
You could mimic the behaviour with some own function for grouping, ordering, sorting and getting the first item of each group. Fo binding all together, you need a pipe function as well.
const
pipe = (...functions) => input => functions.reduce((acc, fn) => fn(acc), input),
groupBy = key => array => array.reduce((r, o) => {
var fn = typeof key === 'function' ? key : o => o[key],
temp = r.find(([p]) => fn(o) === fn(p));
if (temp) temp.push(o);
else r.push([o]);
return r;
}, []),
order = (...keys) => array => array.sort((a, b) => {
var result;
keys.some(k => result = a[k] > b[k] || -(a[k] < b[k]));
return result
}),
select = fn => array => array.map(fn),
first = array => array[0],
data = [{ TimeEdit: "2020-10-29T10:45:00.21Z", Date: "2020-10-29T00:00:00", Parameters: [{ Id: 1, Value: 1 }, { Id: 2, Value: 348 }] }, { TimeEdit: "2020-10-29T10:43:52.22Z", Date: "2020-10-29T00:00:00", Parameters: [{ Id: 1, Value: 12 }, { Id: 2, Value: 348 }] }, { TimeEdit: "2020-10-30T10:47:12.33Z", Date: "2020-10-30T00:00:00", Parameters: [{ Id: 1, Value: 3 }, { Id: 2, Value: 2 }] }],
result = pipe(
groupBy('Date'),
select(
pipe(
order('TimeEdit'),
first
)
)
)(data);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

How to go through a complex object formatting the given required fields using a function passed by parameter?

I'm trying to create a function that goes through a complex object formatting the given fields in an array.
The function must receive the object that must be formatted, then the next parameter is an array with the attributes that must be formatted and finally the last function receives the function that will format the value of the field.
The function must return the object in it's original structure.
my code until now:
const formatFields = (obj = {}) => (fieldsToFormat = []) => (formatFunction = () => {}) => {
let newObj = { ...obj };
for (let [k, v] of Object.entries(obj)) {
if (typeof v === 'object' && v !== null) formatFields(v)(fieldsToFormat)(formatFunction);
if (fieldsToFormat.includes(k)) newObj = { ...newObj, [k]: formatFunction(v) };
else newObj = { ...newObj, [k]: v };
}
return newObj;
}
const toMoney = (num) => '$' + num;
const obj = {
totalAmount: 83.24,
quoteItems:
[ { max: '1',
code: '1',
quantity: 1,
unitPrice: 23.21,
totalPrice: 23.21,
description: 'test'
},{
max: '3',
code: '2',
quantity: 3,
unitPrice: 20.01,
totalPrice: 60.03,
description: 'test2'
} ],
};
const priceFormatAttributes = [
'unitPrice',
'totalPrice',
'totalAmount'
];
console.log(formatFields(obj)(priceFormatAttributes)(toMoney));
The nested objects are not being formatted!
I know this is a logical problem... it's being challenging and I can't move on.
I think that the recursion is wrong but I can't see why!
if anyone has an idea how to solve this in another way it is also welcome.
While I'm not sure what the expected output is I would try this:
const formatFields = (obj = {}) => (fieldsToFormat = []) => (formatFunction = () => {}) => {
let newObj = { ...obj }; // clone object to prevent changing the original object
if (Array.isArray(obj)) { // gotta deal with arrays too unless you want to change them all into objects
newObj = [ ...obj ];
}
for (let [key, value] of Object.entries(obj)) {
if (Array.isArray(newObj)) {
newObj.splice(key - 1, 1); // remove the previous it
newObj.push(formatFields(value)(fieldsToFormat)(formatFunction));
}
else if (typeof value === 'object' && value !== null) {
newObj = { ...newObj, [key]: formatFields(value)(fieldsToFormat)(formatFunction) };
}
else if (fieldsToFormat.includes(key)) {
newObj[key] = formatFunction(value)
}
else newObj = { ...newObj, [key]: value };
}
return newObj;
}
const toMoney = (num) => {
return '$' + num;
}
const obj = {
totalAmount: 83.24,
quoteItems: [
{
max: '1',
code: '1',
quantity: 1,
unitPrice: 23.21,
totalPrice: 23.21,
description: 'test',
},
{
max: '3',
code: '2',
quantity: 3,
unitPrice: 20.01,
totalPrice: 60.03,
description: 'test2',
}
],
};
const priceFormatAttributes = [
'unitPrice',
'totalPrice',
'totalAmount',
];
console.log(formatFields(obj)(priceFormatAttributes)(toMoney));
This outputs:
{
totalAmount: '$83.24',
quoteItems: [
{
max: '1',
code: '1',
quantity: 1,
unitPrice: '$23.21',
totalPrice: '$23.21',
description: 'test'
},
{
max: '3',
code: '2',
quantity: 3,
unitPrice: '$20.01',
totalPrice: '$60.03',
description: 'test2'
}
]
}

Reduce and sort object array in one step

I'm trying to get two values (label and data) from my source data array, rename the label value and sort the label and data array in the result object.
If this is my source data...
const sourceData = [
{ _id: 'any', count: 12 },
{ _id: 'thing', count: 34 },
{ _id: 'value', count: 56 }
];
...the result should be:
{ label: ['car', 'plane', 'ship'], data: [12, 34, 56] }
So any should become car, thing should become plane and value should become ship.
But I also want to change the order of the elements in the result arrays using the label values, which should also order the data values.
Let's assume this result is expected:
{ label: ['ship', 'car', 'plane'], data: [56, 12, 34] }
With the following solution there is the need of two variables (maps and order). I thing it would be better to use only one kind of map, which should set the new label values and also the order. Maybe with an array?!
Right now only the label values get ordered, but data values should be ordered in the same way...
const maps = { any: 'car', thing: 'plane', value: 'ship' }; // 1. Rename label values
const result = sourceData.reduce((a, c) => {
a.label = a.label || [];
a.data = a.data || [];
a.label.push(maps[c._id]);
a.data.push(c.count);
return a;
}, {});
result.label.sort((a, b) => {
const order = {'ship': 1, 'car': 2, plane: 3}; // 2. Set new order
return order[a] - order[b];
})
You could move the information into a single object.
const
data = [{ _id: 'any', count: 12 }, { _id: 'thing', count: 34 }, { _id: 'value', count: 56 }],
target = { any: { label: 'car', index: 1 }, thing: { label: 'plane', index: 2 }, value: { label: 'ship', index: 0 } },
result = data.reduce((r, { _id, count }) => {
r.label[target[_id].index] = target[_id].label;
r.data[target[_id].index] = count;
return r;
}, { label: [], data: [] })
console.log(result);
Instead of separating the data into label and data and then sorting them together, you can first sort the data and then transform.
const sourceData = [
{ _id: 'any', count: 12 },
{ _id: 'thing', count: 34 },
{ _id: 'value', count: 56 }
];
const maps = { any: 'car', thing: 'plane', value: 'ship' };
// Rename label values.
let result = sourceData.map(item => ({
...item,
_id: maps[item._id]
}));
// Sort the data.
result.sort((a, b) => {
const order = {'ship': 1, 'car': 2, plane: 3};
return order[a._id] - order[b._id];
})
// Transform the result.
result = result.reduce((a, c) => {
a.label = a.label || [];
a.data = a.data || [];
a.label.push(c._id);
a.data.push(c.count);
return a;
}, {});
console.log(result);

Categories

Resources