Javascript - Convert JSON Object Property Value from Array to String - javascript

I have an issue where an API call I'm using is sending objects with one property that contains a single array value (keys property in response below). Unfortunately I cannot use this format as I must abide by Nested arrays in order to use the outputted values in a separate application like so [[value1, value2, value3, value4],[value1, value2, value3, value4]]. I plan on asking a separate question to tackle the nested array section unless someone thinks it is an easy fix (I believe I should use .map to convert the object).
Here is the format of my objects (from console.log(searchQueries)):
[ { keys: [ 'hammer' ],
clicks: 1369,
impressions: 3151,
ctr: 0.4344652491272612,
position: 1.004443033957474 },
{ keys: [ 'woodmaking' ],
clicks: 207,
impressions: 6324,
ctr: 0.03273244781783681,
position: 4.35831752055661 },
{ keys: [ 'house trends' ],
clicks: 1,
impressions: 3,
ctr: 0.3333333333333333,
position: 4.666666666666666 },
{ keys: [ 'housing' ],
clicks: 1,
impressions: 36,
ctr: 0.027777777777777776,
position: 6.472222222222222 } ]
byProperty
Above response is passed from the following for-in loop the result of this API response array being nested in an object originally:
for (var prop in res){
searchQueries = res[prop];
console.log(searchQueries);
}
Would the JSON.stringify method or .toString('keys') achieve what I'm looking for?

If you want to turn keys from an array into a string, you just need to iterate over your array and make the change:
searchQueries.forEach(function (obj) { obj.keys = obj.keys[0] })

answer=Object.values(searchQueries).map(el=>{el.keys=el.keys[0];return Object.values(el)});
console.log(searchQueries);
https://jsbin.com/biyazunafu/1/edit?console
Loop over the main array, turn the Objects (el) keys array into a string, than turn the whole object into its values Array. However, Object.values is experimental, so may dont use this on the users side, instead use this code transpiled to ES5 :
answer=[];
for(key in searchQueries){
answer.push(searchQueries[key]);
}
answer=answer.map(function(el){
el.keys=el.keys[0];
var newel=[];
for(key in el){
newel.push(el[key]);
}
return newel;
});

1st Get the keys values
var keys = searchQueries.map(function(e){return e.keys;});
This will output :
[["hammer"], ["woodmaking"], ["house trends"], ["housing"]]
2nd: Concat the resulting array
var values = keys.join(',').split(',');
The result :
["hammer", "woodmaking", "house trends", "housing"]

Related

deconstruct JSON object in JS

I'm trying to deconstruct this object to get "Swiss franc", assuming i don't know the key CHF.
currencies = {CHF: {name: "Swiss franc", symbol: "Fr."}}
My attempts:
Object.values(Object.values(currencies)[0]
// -> Swiss franc,Fr.
Object.values(Object.values(currencies)[0].name
// -> S,w,i,s,s, ,f,r,a,n,c
// why does it split the string?? not retrieve the value based on key name??
// i know how to join the strings back, but i'm confused why is this result?)
just a little modification to your code:
const currencies = {CHF: {name: "Swiss franc", symbol: "Fr."}}
console.log(Object.values(Object.values(currencies)[0])[0])
// OR Simply
console.log(Object.values(currencies)[0].name)
Object.entries Implementation Reference
Explanation
The Object.entries() method returns an array of a given object's own
enumerable string-keyed property [key, value] pairs. This is the same
as iterating with a for...in loop, except that a for...in loop
enumerates properties in the prototype chain as well.
Working Example
const currencies = { CHF: { name: "Swiss franc", symbol: "Fr.", }}
console.log(Object.entries(currencies)[0][1].name);
Code Explanation
Object.entries(currencies)
The above statement return an array as below
[["CHF", {symbol: 'Fr.', name: 'Swiss franc'}]]
An array of combination of key value pairs in the object.
We are interested in the node zero of the array and index one of the first node of array.
So it will be
Object.entries(currencies)[0][1].name
Object.values implementation. Reference.
Explanation
The Object.values() method returns an array of a given object's own
enumerable property values, in the same order as that provided by a
for...in loop. (The only difference is that a for...in loop enumerates
properties in the prototype chain as well.)
Working Example
const currencies = { CHF: { name: "Swiss franc", symbol: "Fr.", }}
console.log(Object.values(currencies)[0].name);
Code Explanation
Object.values(currencies)
Tie above expression will return the array of values. Since we have only one key, the output of above statement will be
[{ symbol: 'Fr.', name: 'Swiss franc' }]
So the requird node will be
Object.values(currencies)[0].name
currencies = {CHF: {name: "Swiss franc", symbol: "Fr."}}
This will do it,
Object.values(currencies)[0].name
Breakdown :-
Object.values(currencies) gives [{name: "Swiss franc", symbol: "Fr."}]
Object.values(currencies)[0] gives {name: "Swiss franc", symbol: "Fr."}
Object.values(currencies)[0].name gives Swiss franc.

How do I access value of an attribute with an object with no key pairs?

I am working with dynamoose and a query returns me the following output
[ Document { cost: 100 },
lastKey: undefined,
count: 1,
queriedCount: undefined,
timesQueried: 1 ]
When I try to do typeof(output) , it returns Object
When I try to do Object.keys(output) , it returns [ '0', 'lastKey', 'count', 'queriedCount', 'timesQueried' ]
When I do Object.entries(output), it returns [ [ '0', Document { cost: 100 } ],[ 'lastKey', undefined ], [ 'count', 1 ], [ 'queriedCount', undefined ], [ 'timesQueried', 1 ] ]
For my use, I need to get an Object which looks like this {cost: 100} and currently I am using
JSON.parse(JSON.stringify(output))
which gives me
[ { cost: 100 } ]
I havent encountered an object without a key value pair (I'm self taught), so I do not know how to approach this problem. And the current method seems inefficient and kinda wrong. Please advice me how I can do it in a proper way
JSON.stringify(output) //=> "[ { cost: 100 } ]"
What that means is that you have an array (denoted by []) with one item, which is an object (denoted by {}) with a single key cost.
Use [0] to get the first item in an array, and then use .cost to get the cost property.
console.log(output[0].cost) //=> 100
The reason that you are seeing other keys on that array is that it looks like that dynamoose library is adding some additional properties to the array before returning it. It's doing the equivalent of:
// vanilla js, not typescript
const output = [ { cost: 100 } ]
output.count = 1
output.timesQueried = 1
This gives the array properties in addition to the content. The dynamoose library appears to use this method to encode metadata about your queries alongside the returned data.
The default JSON serialization strategy for arrays does not serialize custom array properties, only the array members.

Looping through an array of objects and mapping each object them to a single template object

I have a two sets of data, one formatted like so:
title: "Test Json",
showProgressBar: "top",
showQuestionNumbers: "off",
pages: [
{
questions: [
{
type: "",
name: "",
title: "",
hasOther: true,
isRequired: true,
colCount: 4,
choices: []
}
]
}
]
};
The other formatted like so:
{Answers: "“18-24”, “25-50”, “50+”",
​
Question: "How old are you?",
​
QuestionNumber: "1",
​
isRequired: "TRUE",
​
type: "radiogroup"}
This second set of data is multiple of these objects, which I am looping through using a forEach loop like so:
data.forEach((data, i)=>{
console.log(data)
// returns above object x3
})
What I want to do is use the first object and map values to the questions array using the values of the second object, so for example questions[0].type would be mapped to data.type.
I have managed to figure out mapping one object to the template doing this:
data.forEach((data, i)=>{
console.log(data)
questions[0].type = data.type
questions[0].name = data.Question
questions[0].title = data.Question
questions[0].choices = [data.Answers]
})
But this only maps the first object in the data array of objects, and I want to basically create a new template object based on the number of objects in the data array and create as many 'filled questions templates' as there is objects in data array
Any pointers and help would be lovely <3
Try this
data.forEach((data, i)=>{
console.log(data)
questions.push([{
type: data.type
name: data.Question
title: data.Question
choices: [data.Answers]
}])
})
Updated this answer with your additional question

Lodash sorting & ordering deep object by values, without losing the key

I'm having a similar need to a previous post on this topic: needing to order and sort an object without losing the keys. However, I have an object of objects:
var o = {
123: { field: "science", name: "zed" },
234: { field: "tech", name: "sara" },
672: { field: "arts", name: "jon" }
}
_.fromPairs(_.sortBy(_.toPairs(o),function(a){ return a[1] }).reverse())
The above uses the lodash solution mentioned the other topic - I'm however not getting any consistency of results (tho am retaining the key!)
Any help would be appreciated.
I’m not clear on what value you intended to sort against above, since objects are incomparable. Let’s say you wanted to sort them by the name field, though — you would find that it still didn’t work.
First some background:
Historically, object properties were considered unordered in ES. The sequence that keys would be enumerated (e.g. by for ... in or Object.keys()) was implementation-specific.
However enumeration order became a specified behavior in ES2015.
That enumeration order codifies what most engines were already doing:
Keys which are integers are enumerated first, from lowest to highest.
String keys are enumerated in the order of assignment.
Symbol keys are enumerated in the order of assignment.
If you need to use integers as ordered keys, you’ll require a different data structure. Map is appropriate:
const o = {
123: { field: "science", name: "zed" },
234: { field: "tech", name: "sara" },
672: { field: "arts", name: "jon" }
}
const { compare } = new Intl.Collator();
const res = new Map(Object
.entries(o)
.sort(([ , a ], [ , b ]) => compare(a.name, b.name))
);
console.log([ ...res ]);
If you need to worry about old IE, an array of key-value entries would also suffice.

How to convert an array of objects to an object in Lodash?

I have this:
[ { list:
[ [Object],
[Object] ] },
{ head:
[ [Object],
[Object] ] }
]
And want to turn it into this:
{ list:
[ [Object],
[Object] ],
head: [ [Object],
[Object] ]
}
So an array of objects into an object. It would be great to achieve this with lodash.
I think an even shorter solution would be:
Object.assign({}, ...array)
I know you asked for lodash, but it doesn't seem like you even need this way. Unless you want to use _.extend.
_.reduce(array, function(memo, current) { return _.assign(memo, current) }, {})
Here's a shorter version:
_.transform(array, _.ary(_.extend, 2), {});
The transform() function is like reduce(), except it's not expecting you to return anything. Since extend() is altering it's first argument, we can just pass it straight to transform(). It's wrapped in ary() to make sure it only gets 2 arguments passed to it.
To build on #rcsole's great answer, this works well:
states = [{
state: "NY",
name: "New York",
}, {
state: "AZ",
name: "Arizona",
}]
statesObj = Object.assign({}, ...states.map(state => {
return { [state.state]: state.name }
}))
Result:
{
AZ: "Arizona",
NY: "New York",
}
What's going on here?
Let's break this up into multiple pieces:
// Step 1: Transform from [{state: "Foo", name: "Bar"}, ...] to [{Foo: "Bar"}, ...]
mappedStates = states.map(state => { return { [state.state]: state.name } })
// Step 2: Merge all the objects in that array into a single new object
statesObj = Object.assign({}, ...mappedStates)
Step 1 uses map to iterate over every item in the array (every state object). map executes a function for every state object and returns a new object with the state as the key and the name as the value. We need to surround state.state in brackets because it's a dynamic value in an object literal.
Step 2 uses Object.assign to merge all the new state objects in the mappedStates array into a new object (the first parameter, {}).
What are the three dots ... for? That's the spread operator. It takes every element in the mappedStates array and turns them into direct arguments of the Object.assign method.
This example makes it clear:
Object.assign({}, ...mappedStates)
is the same as
Object.assign({}, {AZ: "Arizona"}, {NY: "New York"})
That's it!
Use fromPairs on lodash 4. https://lodash.com/docs#fromPairs
_.fromPairs([['fred', 30], ['barney', 40]]);

Categories

Resources