Format object with some keys to array [closed] - javascript

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 11 months ago.
Improve this question
It gets a specific result from my database which I have shown below:
const data = {
short: 'en',
element: {
'dsdsea-22dada-2ffgd-xxada-eeee': { name: 'test name', comment: 'test comment' },
'adad2a-dda13-dsdad-wwwwd-adaxx': { name: 'name 2' },
}
And I would like to apply a JavaScript operation to be able to get this result:
[
{
short: 'en',
key: "dsdsea-22dada-2ffgd-xxada-eeee.name"
value: "test name"
},
{
short: 'en',
key: "dsdsea-22dada-2ffgd-xxada-eeee.comment"
value: "test comment"
},
{
short: 'en',
key: "adad2a-dda13-dsdad-wwwwd-adaxx.name"
value: "name 2"
}
]
I have tried using a combination of Object.entries and the map function, but I don't know how to deal with double keys in a single element object.

This may be one possible solution to achieve the desired objective.
It uses Object.entries(), .map(), .flatMap() and template literal using backtick `` characters.
Code Snippet
const getTransformedArray = obj => (
Object.entries(obj.element) // iterate over 'element' key-value pairs
.flatMap(([k1, v1]) => ( // k1-v1 where v1 is object (with name, comment props)
Object.entries(v1) // iterate over v1's key-value pairs
.map(([k2, v2]) => ({ // map each iteration
short: obj.short, // create the resulting object
key: `${k1}.${k2}`, // 'key' is created using k1, k2
value: v2 // 'value' is v2 as-is
}))
)) // '.flatMap' used above avoids nesting of arrays
);
const data = {
short: 'en',
element: {
'dsdsea-22dada-2ffgd-xxada-eeee': { name: 'test name', comment: 'test comment' },
'adad2a-dda13-dsdad-wwwwd-adaxx': { name: 'name 2' }
}
};
console.log(getTransformedArray(data));
Explanation
Inline comments in the code-snippet above explain how the code works.
EDIT
Answer updated to use .flatMap() as has been highlighted by #pilchard.

You'll need two loops to iterate over each element and then each value of those elements.
Here using for...of loops on the Object.entries() of each, destructuring at each level to apply relevant names to each property, and then creating a compound key value using a template literal
const data = {
short: 'en',
element: {
'dsdsea-22dada-2ffgd-xxada-eeee': { name: 'test name', comment: 'test comment' },
'adad2a-dda13-dsdad-wwwwd-adaxx': { name: 'name 2' },
}
}
const result = [];
for (const [key, element] of Object.entries(data.element)) {
for (const [prop, value] of Object.entries(element)) {
result.push({ short: data.short, key: `${key}.${prop}`, value })
}
}
console.log(result)

You can do:
const data = {short: 'en',element: {'dsdsea-22dada-2ffgd-xxada-eeee': {name: 'test name',comment: 'test comment'},'adad2a-dda13-dsdad-wwwwd-adaxx': {name: 'name 2'}}}
const result = Object
.entries(data.element)
.reduce((a, [key, obj]) => [
...a,
...Object
.values(obj)
.map(value => ({
...{
short: data.short,
key
},
value
}))
], [])
console.log(result)

Use Object.keys() to get the keys in element, then map the returned array using the key to access each element object and thus getting the name.
Here's the full code snippet:
const input = {
short: 'en',
element: {
'dsdsea-22dada-2ffgd-xxada-eeee': { name: 'test name', comment: 'test comment' },
'adad2a-dda13-dsdad-wwwwd-adaxx': { name: 'name 2' },
},
};
function format(data = {}) {
const { short = '', element = {} } = data;
let result = Object.keys(element).map((key) => {
return Object.values(element[key]).map((value) => ({ short, key, value }));
});
result = result.flat();
return result;
}
const result = format(input);
console.log(result)
this prints:
[
{
"short": "en",
"key": "dsdsea-22dada-2ffgd-xxada-eeee",
"value": "test name"
},
{
"short": "en",
"key": "dsdsea-22dada-2ffgd-xxada-eeee",
"value": "test comment"
},
{
"short": "en",
"key": "adad2a-dda13-dsdad-wwwwd-adaxx",
"value": "name 2"
}
]

Related

Javascript: How to iterate through an array looking for an object value?

I have a js file that is just a an array with the name and type of person. I am trying to write a function in my other file to iterate through that array of objects and return just the object that matches a certain criteria. Here is my code.
person.js
export const persons_options = [
{
name: 'Andrew',
type: 'Athlete',
},
{
name: 'Paul',
type: 'Worker',
},
{
name: 'Phil',
type: 'Developer',
},
]
utils.js
// params initialized already
person_type = params.subType
const name = persons_options.map((option) => {
if(person_type === option.type){
return option.name
}
})
const person = name
The issue is I know map creates a new array so the output is ,,Phil. How would I just return one of the object names instead of all of them.
find() will do the work
let persons_options = [
{
name: 'Andrew',
type: 'Athlete',
},
{
name: 'Paul',
type: 'Worker',
},
{
name: 'Phil',
type: 'Developer',
},
]
let obj = persons_options.find(o => o.type === 'Developer');
//to return name
console.log("name",obj.name);
console.log(obj);
You need to use the find function.
See here the list of functions that you can call on an array:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array#instance_methods
filter might best suit your case if multiple results may be returned.

Find the difference between two arrays based on some the value inside a nested array

I have two arrays
arrayOfItems: [
{
id: '4321-3321-4423',
value: 'some text'
},
{
id: '4322-4654-9875',
value: 'some text again'
}
]
Then the second array
itemX: [
{
id: '3214-6543-4321',
nestedArrayOfItems:[
{id: '4321-3321-4423'}
{id: '3455-8765-7764'}
]
}
]
I need to create a new array based on arrayOfItems that doesn't include any of the id's in the itemX.nestedArrayOfItems
Because of it being a nested Array I'm drawing a blank on what I need to do... I'm searching through Lodash to see if there is something that doesn't involve me using a bunch of for loops.
You can use Array.prototype.filter() and then check if the id exists with
Array.prototype.some() like so:
const arrayOfItems = [
{
id: '4321-3321-4423',
value: 'some text'
},
{
id: '4322-4654-9875',
value: 'some text again'
}
]
const itemX = [
{
id: '3214-6543-4321',
nestedArrayOfItems: [
{id: '4321-3321-4423'},
{id: '3455-8765-7764'}
]
}
]
const res = arrayOfItems.filter(item => !itemX[0].nestedArrayOfItems.some(({ id }) => id === item.id))
console.log(res);
how about this :
let difference = arrayOfItems.filter(x => ! itemX.nestedArrayOfItems.includes(x));
PS : ids must be string

Iterate array in reactjs

allInfo.map((name) => console.log("arr", name.firstName))
The above statement is an array. I want to iterate the values and put them in the following array to show it in the dropdown.
const info = [
{ value: "firstName", label: "firstName" },
{ value: "first",label: "first"},
{ value: "lastName", label: "lastName" }
]
I want to iterate the value of allInfo and put it inside the value of info. Instead of value = "firstName", I want to get it from the allInfo array. Can anyone help me with this?
Just map the allInfo array directly to get the info array.
const info = allInfo.map(name => ({
value: name.firstName,
label: name.firstName,
}));
If you want to have some static values in the info array too, you can use the spread operator like this:
const allInfoItems = allInfo.map(name => ({
value: name.firstName,
label: name.firstName,
}));
const info = [
{ value: 'something', label: 'something' },
...allInfoItems
]

Javascript - transform an object of array list to another format?

So I've been stumped on this for hours and I can't really figure out an elegant solution to solve this problem. Let's say I have this:
let Fields = {
GAME: [
{ code: '{{GTAV}}', title: { en: "grnti"} },
{ code: '{{GTA5}}', title: { en: "Grand theph " } },
]
};
How can I turn this into a new format that looks like this ?
let Fields = {
tags: [
{ name: 'GAME', tags:[
{ name: 'grnti', value: "{{GTAV}}" },
{ name: 'Grand theph', value: "{{GTA5N}}" }
]},
]};
I tried to create a function to do the job , but for some reason my brain cannot seem to grasp the solution. Any help please !
A simple version of this might look like the following:
const transform = (fields) => ({
mergeTags: Object .entries (fields) .map (([name, innerFields]) => ({
name,
mergeTags: innerFields .map (({code, title: {en}}) => ({name: en, value: code}))
}))
})
const fields = {RECIPIENT: [{code: '{{RECIPIENT.LN}}', title: {en: "name"}}, {code: '{{RECIPIENT.FN}}', title: {en: "first name" }}]}
console .log (transform (fields))
But from your nested mergeTags properties, I'm guessing that there is something recursive going on. If so, we need more information about the input and output structures.
i just threw a nested reduce function together.
const transformed = Object.entries(Fields).reduce((tags, [key, value]) => {
const mergedTags = value.reduce((codes, code) => {
codes.mergeTags.push({name: code.title.en, value: code.code});
return codes;
}, {name: key, mergeTags: []})
tags.mergeTags.push(mergedTags)
return tags;
}, {mergeTags: []})
Does that work for you?
It is hard to tell exactly from your question what you are hoping to accomplish as well as the shape of your data. Based on your question though, you would probably want to use the Object.keys and map functions
let Fields = {
RECIPIENT: [
{ code: '{{RECIPIENT.LN}}', title: { en: "name" } },
{ code: '{{RECIPIENT.FN}}', title: { en: "first name" } },
]
};
// gets the keys of the 'Fields' object(in this case only 'RECIPIENT'
let newFields = Object.keys(Fields)
// each key should create a new object with the 'key' from the original object as the 'name' of the new object
.map(key => ({
name: key,
// 'Fields[key]' gets the array from the 'RECIPIENT' property and then creates a new object from each object in the original array, mapping the 'title.en' property in the original object to 'name' in the new object and 'code' in the original object to 'value' in the new object
mergeTags: Fields[key].map(property => ({
name: property.title.en,
value: property.code
}))
}));
console.log(newFields);
Here's a clean way that may seem a bit like magic, but I'll walk you through what's going on.
let Fields = {
RECIPIENT: [
{ code: '{{RECIPIENT.LN}}', title: { en: "name"} },
{ code: '{{RECIPIENT.FN}}', title: { en: "first name" } },
]
};
const { pipe, fork, map, get } = rubico
const Transformed = pipe([
Object.entries, // { RECIPIENT: [...] } => [['RECIPIENT', [...]]
fork({
mergeTags: map(fork({ // iterate through each entry ['RECIPIENT', [...]]
name: get(0), // name is the item at index 0 of each entry
mergeTags: pipe([
get(1), // mergeTags starts with index 1 of each entry, the array of code+title objects
map(fork({ // iterate through the array of code + title objects and create new objects
name: get('title.en'), // name is title.en of each object
value: get('code'), // value is title.code of each object
})),
]),
})),
}),
])(Fields)
console.log(JSON.stringify(Transformed, null, 2))
<script src="https://unpkg.com/rubico"></script>
Disclaimer: I am the author of rubico
You can examine these methods in depth at the documentation

Map or Each for Values with Underscore.js

I am trying to figure out the best way to update my underscore.js .map method since the inclusion of a new field value that should be grouped with the current value being passed to .map. Should I use .map or .each with the new update and should I store the values as an object or object in an array and pass that to the .map or .each to achieve my desired outcome? At the moment I tried the object approach with .map, but the values are coming through as arrays.
Proper format:
[ { reportTitle: 'Title1', reportLink: 'test.com', id: 166 },
{ reportTitle: 'Title2', reportLink: 'test2.com', id: 166 } ]
Original (Working):
var links = _.map(req.body.reportLink, function(link){
return {
reportLink: link,
id: blog.id
};
});
Output:
[ { reportLink: 'test.com', id: 166 },
{ reportLink: 'test2.com', id: 166 } ]
Updated (Not Working):
var linkAttributes = { title: req.body.reportTitle, link: req.body.reportLink}
var links = _.map(linkAttributes, function(link) {
return {
reportTitle: link.title,
reportLink: link.link,
id: blog.id
};
});
Output:
[ { reportTitle: [ 'Test 1', 'Test 2' ],
reportLink: [ 'test1.com', 'test2.com' ],
id: 164 } ]
It is now clear what it is you're asking, the following should do the trick:
const zip = (arr1, arr2) =>
[...new Array(Math.max(arr1.length, arr2.length))].map(
(_, i) => [arr1[i], arr2[i]],
);
const reportTitle = ['test-title', 'test-title2'];
const reportLink = ['test.com', 'test2.com'];
console.log(
zip(reportTitle, reportLink).map(
([reportTitle, reportLink]) => ({
reportTitle,
reportLink,
id: 166,
}),
),
);
The zip utility takes 2 arrays (for example [1,2,3] and [5,6,7]) and returns an array with an element from each array: ([[1,5],[2,6],[3,7] from the example)
Then it maps over this array to create an array of objects.
The function passed to map uses destructuring parameters to quickly name the 2 elements from the array passed to the map function.
_.map -> shoud have first argument as array
var linkAttributes = [
{
title: req.body.reportTitle,
link: req.body.reportLink
}
]; // shoud be array
var links = _.map(linkAttributes, function(link) {
return {
reportTitle: link.title,
reportLink: link.link,
id: blog.id
};

Categories