turning an array into an array with objects - javascript

I have been trying to figure out how to turn an array into an array with objects.
for example i have a json file to start with and the json file looks sorta like this
var data=[{"tasknumber":304030,
"date":"2012-05-05",
"operator":"john doe"},
{"tasknumber":23130,
"date":"2012-07-07",
"operator":"john doeeeeeeee"},
{"tasknumber":233330,
"date":"2012-08-08",
"operator":"john doe"}]
so i applied the _.countBy function that is within the underscore.js library and i get an object like this
{"john doe":2,"john doeeeeeeee":1}
ive been trying to figure out how to turn this into an array with objects so it would look something like this but i have failed in every attempt and i dont know were to start
[{operator:"john doe",
count: 2},
{operator: "john doeeeeeeee",
count:1}]
i have tried a few things but all i get is tragedy and everything breaks, does anyone know if there are any librarys or anything that could help with this sort of thing?

Given the object (not array) {"john doe":2,"john doeeeeeeee":1} as input you can get your desired output like this:
var input = {"john doe":2,"john doeeeeeeee":1};
var output = Object.keys(input).map(function(k) {
return {
operator: k,
count: input[k]
};
});
console.log(output);
Or with ES6 arrow function syntax:
var input = {"john doe":2,"john doeeeeeeee":1};
var output = Object.keys(input).map((k) => ({ operator: k, count: input[k] }) );
console.log(output);
(Note that Underscore probably provides an even shorter way to do this, but I'm not familiar with Underscore so I've just given a plain JS solution.)
Further reading:
Object.keys()
array .map()
=> arrow functions

Given your initial data array, you can just run this:
var data=[{"tasknumber":304030,
"date":"2012-05-05",
"operator":"john doe"},
{"tasknumber":23130,
"date":"2012-07-07",
"operator":"john doeeeeeeee"},
{"tasknumber":233330,
"date":"2012-08-08",
"operator":"john doe"}];
Function definition
const count = data => {
// get data in format like _.countBy
const o = data.map(x => x.operator).reduce((acc, cur) => { acc[cur] ? acc[cur] += 1 : acc[cur] = 1; return acc; }, {});
// transform object into array of object
return Object.keys(o).map(operator => ({operator, count: o[operator]}));
};
Test it by producing output
console.log(count(data));

Here is an untested underscore approach that takes your initial values as loaded from the JSON file and converts directly into your desired output format:
_.chain(input)
.groupBy(function(entry) { return entry.operator })
.map(function(entries, operator) {
return {
operator: operator,
count: entries.length
}
})
.value();

Related

Getting multi-dimensional array value using Javascript / node.js

I have an Object that looks like this>
let arr = [
['animal','lion'],
['plant','rose'],
['tree','coconut'],
]
I want to make my code look like this:
['animal','lion']
['plant','rose']
['tree','coconut']
For this, I tried this method:
let sep1=arr[0];
let sep2=arr[1];
Getting value as:
['animal','lion']
['plant','rose']
I have to repeat the code 3 time to get the output, but what if there is 30 arrays inside an object? Any solution?
Ps: I am weak in coding bear with me :slight_smile:
If you want to be able to access the separate arrays by key, you could map() through your array and create entries to create an object from. That way, you could access a specific array by property key.
let arr = [
['animal', 'lion'],
['plant', 'rose'],
['tree', 'coconut'],
];
const result = Object.fromEntries(arr.map((a, i) => {
return [`sep${i}`, a]; // return ['sepX', [x, x]] as entries
}));
console.log("result", result);
console.log("sep0", result.sep0);
console.log("sep1", result.sep1);
console.log("sep2", result.sep2);

Javascript - Workaround for flatmap

So I was looking for some workaround for flat map as it doesn't work on IE and I find this one:
But I don't really understand why does it work
var gadjets = [
{computers:['asus', 'hp'],
sellphones:['Galaxy', 'Nokia']
},
{computers:['dell', 'insys'],
sellphones:['iphone', 'samsung']
}
];
const getValues = gadjets.reduce((acc, gadjet) => acc.concat(gadjet[computers]), []) // instead of gadjets.flatMap(gadjet=> gadjet[computers])
This code returns:
['asus','hp','dell','insys']
But shouldn't it return:
['asus','hp'],['dell', 'insys']
This is because reduce adds up the elements you give it. For example, take the following code:
let arr = [1,2,3,4,5];
console.log(arr.reduce((before, value)=>before+value));
This code takes each value and adds it to before. It then passes that added value into the next iteration of reduce, in the before variable.
In your code, you were passing an array into before, or in your case acc, and concatenates (merge) a new array from gadgets['computers'] and returns that array. This creates a list of the computers from the array of objects.
More info on reduce here.
But shouldn't it return
I'm not sure what you're trying to show us there, but if you mean
[['asus','hp'],['dell', 'insys']]
then no, it shouldn't. concat flattens arrays you pass it (to a single level):
const a = [].concat(['asus','hp'], ['dell', 'insys']);
console.log(a); // ["asus", "hp", "dell", "insys"]
So acc.concat(gadjet[computers]) flattens out each of those computers arrays into a new array, which is the accumulation result of the reduce.
In case you want the output to be array of arrays. Try this:
var gadjets = [
{ computers: ["asus", "hp"], sellphones: ["Galaxy", "Nokia"] },
{ computers: ["dell", "insys"], sellphones: ["iphone", "samsung"] }
];
const groupBy = key => {
let res = gadjets.reduce((objectsByKeyValue, obj) => {
let arr = [];
arr.push(obj[key]);
return objectsByKeyValue.concat(arr);
}, []);
return res;
};
console.log(groupBy("computers"));

es6 Array Reduce function and string split usage

I'm trying to use the array reduce function to return a 2D array of objects. The input is a comma separated values. The first row of the string is used as the title row. I'm analyzing the solution and I don't understand the notation. Specifically I don't understand the "=> ((obj[title] =
values[index]), obj), {})" portion in the code below. I'm looking to have someone explain it to me. For me it seems like we're initializing obj to be a an object. After that I'm lost.
const CSV_to_JSON = (data, delimiter = ',') => {
const titles = data.slice(0, data.indexOf('\n')).split(delimiter);
return data
.slice(data.indexOf('\n') + 1)
.split('\n')
.map(v => {
const values = v.split(delimiter);
return titles.reduce(
(obj, title, index) => ((obj[title] = values[index]), obj)
, {});
});
};
console.log(CSV_to_JSON('col1,col2\na,b\nc,d')); // [{'col1': 'a', 'col2': 'b'}, {'col1': 'c', 'col2': 'd'}];
console.log(CSV_to_JSON('col1;col2\na;b\nc;d', ';')); // [{'col1': a', 'col2': 'b'}, {'col1': 'c', 'col2': 'd'}]
It's an (ab)use of the comma operator, which takes a list of comma-separated expressions, evaluates the first expression(s), discards them, and then the whole (...) resolves to the value of the final expression. It's usually something only to be done in automatic minification IMO, because the syntax looks confusing.
The .reduce there
return titles.reduce((obj, title, index) => ((obj[title] =
values[index]), obj), {});
is equivalent to
return titles.reduce((obj, title, index) => {
obj[title] = values[index];
return obj;
}, {});
which makes a lot more sense - it turns an array of titles (eg ['foo', 'bar']) and an array of values (eg ['fooVal', 'barVal']), and uses .reduce to transform those into a single object, { foo: 'fooVal', bar: 'barVal' }.
The first argument to the .reduce callback is the accumulator's initial value (the second argument to .reduce), or the value that was returned on the last iteration - the code above passes {} as the initial value, assigns a property to the object, and returns the object on every iteration. .reduce is the usually the most appropriate method to use to turn an array into an object, but if you're more familiar with forEach, the code is equivalent to
const obj = {};
titles.forEach((title, index) => {
obj[title] = values[index];
});
return obj;
While the comma operator can be useful when code-golfing, it's probably not something that should be used when trying to write good, readable code.

Create JSON string from a Map with arrays as entries

My data structure object is a Map with the following structure:
{
"2018-09-25":[0,1,2,0,8],
"2018-10-17":[0,2,0,0,0],
"2018-10-26":[0,2,1,0,0],
"2018-10-29":[0,2,2,1,0],
"2018-10-31":[0,3,2,1,0],
"2018-11-01":[0,3,3,1,0],
"2018-11-02":[0,4,4,1,0]
}
I use JSON.stringify and then JSON.parse. However, I would need the elements to be somehow named so that I can reference them (e.g. when drawing a chart).
I tried the following but I get NaN as a value.
data = Object.keys(data).map(function (k) {
return {date: new Date(k), value: +data[k]};
});
I would like to have something like this:
Key: "2018-09-25"
1:0
2:1
3:2
4:0
5:8
Since you are using map() it looks like you want an array as a final result. But, since the array will be a different size, map() doesn't really work. You can use reduce to flatten out the inner arrays into one big array:
let o = {"2018-09-25":[0,1,2,0,8],
"2018-10-17":[0,2,0,0,0],
"2018-10-26":[0,2,1,0,0],
"2018-10-29":[0,2,2,1,0],
"2018-10-31":[0,3,2,1,0],
"2018-11-01":[0,3,3,1,0],
"2018-11-02":[0,4,4,1,0]
}
let newAr = Object.entries(o).reduce((arr, [key, values]) => {
return arr.concat(values.map(n => ({date: new Date(key), value: n})))
}, [])
console.log(newAr)
Is that what you're after?

Converting an Array into object in Javascript

I want to know the best way to convert an array in Js to object.
This is the sample of what i want to do.
Input => ['abc', 'def'];
Output => { abc: true, def: true }
I have done it using the code below. But just wanted to know if
**function toObject(strings) {
var rv = {}
strings.forEach(string => {
rv[string] = true
})
return rv
}**
This function serves the purpose. But any experts out there with a best and efficient way possible.
Not sure what you mean by best and efficient way possible, since yours is alright according to me, this is a less versbose version
var output = strings.reduce( (a,c) => (a[c]=true, a), {})
Demo
var strings = ['abc', 'def'];
var output = strings.reduce( (a,c) => (a[c]=true, a), {});
console.log(output);
You could map single objects and assign it to the same object.
var array = ['abc', 'def'],
object = Object.assign(...array.map(key => ({ [key]: true })));
console.log(object);

Categories