Javascript (Underscore), function to change javascript object [duplicate] - javascript

This question already has answers here:
Javascript, Transforming object with underscore (or not)
(2 answers)
Closed 7 years ago.
Trying to change an object to prepare it for send by taking the array inside and turning it into an object with the items in the array being keys with values of true.
It starts out looking like -
{"state":["Saved","Published"],"discipline":["Marketing"]}
So the end result would look like
{"state":{"Saved":true,"Published":true},"discipline":{"Marketing":true}}
So it just looks at that array and changes it to an object with values of true. I am trying to use underscore but plain js would work just fine.
Here is my attempt, is there a better way to do this, maybe with underscore? -
function transformOutputToFilterModel(model) {
var transformedObj = _.map(model, function(obj) {
return obj.reduce(function(obj, k) {
obj[k] = true;
return obj;
}, {})
});
return transformedObj;
}
Thanks for reading!
Edit - sorry I had marked an answer wihtout realizing it wasn't exactly corret. I have this function -
var transformedObj = _.map(model, function(obj) {
return obj.reduce(function(obj, k) {
obj[k] = true;
return obj;
}, {});
});
this does format the inside object correctly, however it is pulling off the outer keys - see here : https://jsfiddle.net/d0kjctfh/3/
Those outer objecst should have the keys of state and discipline like this -
{"state":{"Saved":true,"Committed":false,"Published":false},"discipline":{"Marketing":true}};
Thanks!

You need to do it in several steps:
_.mapObject(model, function(vals) {
return _.object(vals, _.map(vals, function() { return true; }));
} );
The map just makes a list of trues the right length, the _.object changes ["Saved","Published"] into {"Saved":true,"Published":true} and the _.mapObject applies it to every field.

I think _.map will always return an array so its not the best solution. Try the code bellow.
var t = {"state":["Saved","Published"],"discipline":["Marketing"]},
newObj = {};
_.each(t, function(obj, index) {
newObj[index] = {};
if(_.isArray(obj)){
var toReturn = {};
_.each(obj, function(index,item){
toReturn[index] = true;
});
newObj[index] = toReturn;
}
});
console.log(newObj);

No need for underscore; Array.map() is native Javascript. However, map returns an array, which isn't what you want. Try reduce, accumulating the results into an (initially) empty object:
var input = {"state":["Saved","Published"],"discipline":["Marketing"]};
var toObject = function(arr) {
return arr.reduce(function(prev,curr){
prev[curr]=true;
return prev;
},{});
}
console.log(toObject(input.state));

var input = {"state":["Saved","Published"],"discipline":["Marketing"]};
function childToObj(arr) {
return arr.reduce(function(prev,curr){
prev[curr]=true;
return prev;
},{});
}
for (var key in input) {
if (input.hasOwnProperty(key)) {
input[key] = childToObj(input[key]);
}
}
console.log(input);
console.log(JSON.stringify(input));

Sometimes the easiest way is the classic way:
function prepareObject(obj){
var i, e, o = {};
for(e in obj){
if(obj.hasOwnProperty(e)){
o[e] = {};
for(i = 0; i <= obj[e].length - 1; i++) {
obj[e][obj[e][i]] = true;
}
}
}
return o;
}
Optimized / minify
window.prepareObject=function(b){var c,a,d={};for(a in b)if(b.hasOwnProperty(a))for(d[a]={},c=0;c<=b[a].length-1;c++)b[a][b[a][c]]=!0;return d};

Related

How to group all values that have the same key into an array

First, sorry if you find the question confusing.
Basically, I have an object like this:
[{"6":6.5},{"4":4.2},{"6":6.3}]
What I want to do, is to remove the duplicated keys but keep there values and push them all into one unique key only, as an array. like this:
[{"6":[6.5, 6.3]}, {"4": 4.2}]
Can anyone suggest a solution?
.reduce() is what you want:
var data = [{"6":6.5},{"4":4.2},{"6":6.3}];
var res = data.reduce((rv, obj) => {
var key = Object.keys(obj)[0];
rv[key] = rv[key] || [];
rv[key].push(obj[key]);
return rv;
}, {});
console.log(res);
Note: This returns data always in the format of arrays (Even if there is one value). If you're looking for the exact format you specified, you just need to add more logic as I've demonstrated below (Although, I wouldn't recommend this approach, as it adds more complication down the line.)
var data = [{"6":6.5},{"4":4.2},{"6":6.3}];
var res = data.reduce((rv, obj) => {
var key = Object.keys(obj)[0];
if (Array.isArray(rv[key])) { // Already is an array
rv[key].push(obj[key]);
} else if (rv[key] !== undefined) { // Has a value. Convert to array
rv[key] = [rv[key], obj[key]];
} else { // Haven't seen this key yet. Set the value
rv[key] = obj[key];
}
return rv;
}, {});
console.log(res);

JavaScript - Filter <key,value> Object by key

I am looking for a short and efficient way to filter objects by key, I have this kind of data-structure:
{"Key1":[obj1,obj2,obj3], "Key2":[obj4,obj5,obj6]}
Now I want to filter by keys, for example by "Key1":
{"Key1":[obj1,obj2,obj3]}
var object = {"Key1":[1,2,3], "Key2":[4,5,6]};
var key1 = object["Key1"];
console.log(key1);
you can use the .filter js function for filter values inside an object
var keys = {"Key1":[obj1,obj2,obj3], "Key2":[obj4,obj5,obj6]};
var objectToFind;
var keyToSearch = keys.filter(function(objects) {
return objects === objectToFind
});
The keyToSearch is an array with all the objects filter by the objectToFind variable.
Remember, in the line return objects === objectToFind is where you have to should your statement. I hope it can help you.
You can create a new object based on some custom filter criteria by using a combination of Object.keys and the array .reduce method. Note this only works in es6:
var myObject = {"Key1":["a","b","c"], "Key2":["e","f","g"]}
function filterObjectByKey(obj, filterFunc) {
return Object.keys(obj).reduce((newObj, key) => {
if (filterFunc(key)) {
newObj[key] = obj[key];
}
return newObj;
}, {});
}
const filteredObj = filterObjectByKey(myObject, x => x === "Key1")
console.log(filteredObj)
Not sure what exactly are you trying to achieve, but if you want to have a set of keys that you would like to get the data for, you have quite a few options, one is:
var keys = ['alpha', 'bravo'];
var objectToFilterOn = {
alpha: 'a',
bravo: 'b',
charlie: 'c'
};
keys.forEach(function(key) {
console.log(objectToFilterOn[key]);
});

how to convert object into array of objects (or collection of objects)

Searched and searched, can't find this, but I'm assuming it's easy.
I'm looking for the lodash "object" equivalent of lodash _.pairs() - but I want an array of objects (or a collection of objects).
Example:
// Sample Input
{"United States":50, "China":20}
// Desired Output
[{"United States":50}, {"China":20}]
Would something like this be sufficient? It's not lodash, but...
var input = {"United States":50, "China":20};
Object.keys(input).map(function(key) {
var ret = {};
ret[key] = input[key];
return ret;
});
//=> [{"United States":50}, {"China":20}]
Using lodash, this is one way of generating the expected result:
var res = _.map(obj, _.rearg(_.pick, [2,1]));
The above short code snippet can be confusing. Without using the _.rearg function it becomes:
_.map(obj, function(v, k, a) { return _.pick(a, k); });
Basically the rearg function was used for reordering the passed arguments to the pick method.
ok, if you must:
var input = {"United States":50, "China":20};
var ouput = _.map(input, function(val, key){ var o = {}; o[key] = val; return o; });
but this is not better than the previous answer. its worse.

Javascript Map Array Loop

I have This simple array :
var gdpData = {"CA": 1,"US": 2,"BF": 3,"DE": 4};
I want to find the value of BF using a loop
how can I do this by loop using JQuery or Javascript?
That's a object literal and not an array.
You can just call:
gdpData.BF // -> returns 3
You can
var res = gdpData["BF"];
or
var res = gdpData.BF;
You can also use the jquery each function
var gdpData = {"CA": 1,"US": 2,"BF": 3,"DE": 4};
jQuery.each(gdpData, function(key, value) {
if(key == "BF") {
alert(value)
}
})
for(var key in gdpData){
if(gdpData[key] == "BF") // do something ...
}
Note you have an object though, not an array. an object is more like a hashmap
Sure, you CAN use your own personal loop, but there's really not point because javascript does the hard work for you.
var obj = { 'a':1, 'b':2, 'c':3 };
var res = obj['a'];
But if you REALLY want to use a loop for some weird reason...
function findValue (obj, item) {
for (key in obj) {
if (key === item) {
return obj[key]; // OH LOOK - that's exactly the same thing.
}
}
return undefined;
}
var obj = { 'a':1, 'b':2, 'c':3 };
var res = findValue(obj, 'a');
Try this:
var gdpData = {"CA": 1,"US": 2,"BF": 3,"DE": 4};
for(var i in gdpData){
if("BF" === i){
alert(gdpData[i]);
}
}
sorry for the 'var'

Sorting a JavaScript object by property name

I've been looking for a while and want a way to sort a Javascript object like this:
{
method: 'artist.getInfo',
artist: 'Green Day',
format: 'json',
api_key: 'fa3af76b9396d0091c9c41ebe3c63716'
}
and sort is alphabetically by name to get:
{
api_key: 'fa3af76b9396d0091c9c41ebe3c63716',
artist: 'Green Day',
format: 'json',
method: 'artist.getInfo'
}
I can't find any code that will do this. Can anyone give me some help?
UPDATE from the comments:
This answer is outdated. In ES6 objects keys are now ordered. See this question for an up-to-date answer
By definition, the order of keys in an object is undefined, so you probably won't be able to do that in a way that is future-proof. Instead, you should think about sorting these keys when the object is actually being displayed to the user. Whatever sort order it uses internally doesn't really matter anyway.
By convention, most browsers will retain the order of keys in an object in the order that they were added. So, you could do this, but don't expect it to always work:
function sortObject(o) {
var sorted = {},
key, a = [];
for (key in o) {
if (o.hasOwnProperty(key)) {
a.push(key);
}
}
a.sort();
for (key = 0; key < a.length; key++) {
sorted[a[key]] = o[a[key]];
}
return sorted;
}
this function takes an object and returns a sorted array of arrays of the form [key,value]
function (o) {
var a = [],i;
for(i in o){
if(o.hasOwnProperty(i)){
a.push([i,o[i]]);
}
}
a.sort(function(a,b){ return a[0]>b[0]?1:-1; })
return a;
}
The object data structure does not have a well defined order. In mathematical terms, the collection of keys in an object are an Unordered Set, and should be treated as such.
If you want to define order, you SHOULD use an array, because an array having an order is an assumption you can rely on. An object having some kind of order is something that is left to the whims of the implementation.
Just use sorted stringify() when you need to compare or hash the results.
// if ya need old browser support
Object.keys = Object.keys || function(o) {
var result = [];
for(var name in o) {
if (o.hasOwnProperty(name))
result.push(name);
}
return result;
};
var o = {c: 3, a: 1, b: 2};
var n = sortem(o);
function sortem(old){
var newo = {}; Object.keys(old).sort().forEach(function(k) {new[k]=old[k]});
return newo;
}
// deep
function sortem(old){
var newo = {}; Object.keys(old).sort().forEach(function(k){ newo[k]=sortem(old[k]) });
return newo;
}
sortem({b:{b:1,a:2},a:{b:1,a:2}})
Here is a one-liner for you.
Array.prototype.reduce()
let data = {
method: 'artist.getInfo',
artist: 'Green Day',
format: 'json',
api_key: 'fa3af76b9396d0091c9c41ebe3c63716'
};
let sorted = Object.keys(data).sort().reduce( (acc, currValue) => {
acc[currValue] = data[currValue];
return acc;
}, {});
console.log(sorted);
Good luck!!
ES5 Compatible:
function sortByKey(obj) {
var keys = Object.keys(obj);
keys.sort();
var sorted = {};
for (var i = 0; i < keys.length; i++) {
var key = keys[i];
sorted[key] = obj[key];
}
return sorted;
}
This should be used with caution as your code shouldn't rely on Object properties order. If it's just a matter of presentation (or just for the fun !), you can sort properties deeply like this :
function sortObject(src) {
var out;
if (typeof src === 'object' && Object.keys(src).length > 0) {
out = {};
Object.keys(src).sort().forEach(function (key) {
out[key] = sortObject(src[key]);
});
return out;
}
return src;
}

Categories