If I have an array of objects like this:
var mountains = [
{ name: 'Kebnekaise', elevation: 2106 },
{ name: 'Mount Ngauruhoe', elevation: 2291, comment: 'aka Mount Doom' }
];
How to get all unique keys i.e. ['name', 'elevation', 'comment']?
In ECMAScript 2015, it's really simple:
let mountains = [
{ name: 'Kebnekaise', elevation: 2106 },
{ name: 'Mount Ngauruhoe', elevation: 2291, comment: 'aka Mount Doom' }
];
let uniqueKeys = Object.keys(Object.assign({}, ...mountains));
Using ES6, one could do
var unique = new Set([].concat.apply([],mountains.map(Object.keys)))
Without ES6, something like
var unique = [].concat.apply([],mountains.map(Object.keys)).filter(function(value,i,arr) {
return arr.indexOf(value) === i;
});
You could iterate over the array of objects and iterate over each element's keys with Object.keys(obj), adding them to a hash to avoid duplicates:
function getKeySet (data) {
var keys = {};
data.forEach(function (datum) {
Object.keys(datum).forEach(function (key) {
keys[key] = true;
});
});
return Object.keys(keys);
}
Alternately you could add all the keys to an array and filter out duplicates. Either way this will be O(nm) where n is the number of elements in the array and m is the average number of keys.
Related
I have this array above and I need every property of it
let arr = [{'John': 0}, {'Doe': 50}, {'Marry': 100}]
How could I extract every single key/value of it, once in theory, I don't know any of them?
I have already tried using object.keys but it returns the indexes of my array.
This should work
const arr = [{'John': 0}, {'Doe': 50}, {'Marry': 100}];
// to iterate over each element in the arry
arr.forEach(a => {
// To Iterate over each key in the element object
Object.keys(a).forEach(k => {
// to print the value of the 'k' key
console.log(k + ' : ' + a[k]);
})
})
1) You can use flatMap and Object.keys to get keys from an array of objects.
let arr = [{ John: 0 }, { Doe: 50 }, { Marry: 100 }];
const result = arr.flatMap((o) => Object.keys(o));
console.log(result);
2) To find all values in an array
let arr = [{ John: 0 }, { Doe: 50 }, { Marry: 100 }];
const values = arr.flatMap((o) => Object.values(o));
console.log(values);
3) If you want to find out all keys and values in an object
let arr = [{ John: 0 }, { Doe: 50 }, { Marry: 100 }];
const result = {
keys: [],
values: [],
};
for (let obj of arr) {
Object.entries(obj).map(([k, v]) => {
result.keys.push(k);
result.values.push(v);
});
}
console.log(result);
If you want to collect all the keys and values of a nested array of objects, you can use Array.prototype.reduce and then collect the keys and values of the nested objects in separate nested arrays, using Object.keys() and Object.values() respectively:
const arr = [{'John': 0}, {'Doe': 50}, {'Marry': 100}];
const allKeysAndValues = arr.reduce((acc, cur) => {
acc.keys.push(...Object.keys(cur));
acc.values.push(...Object.values(cur));
return acc;
}, { keys: [], values: [] });
console.log(allKeysAndValues);
A one liner could be
let arr = [{'John': 0}, {'Doe': 50}, {'Marry': 100}]
console.log( arr.map( obj => Object.entries(obj)));
I have the following two objects
var productionTime= [
{Rob3: 20},
{Rob8: 100},
{Rob4: 500},
{Rob1: 100},
{Rob5: 500}
];
var Busytime= [
{Rob4: 10},
{Rob3: 200},
{Rob8: 100},
{Rob5: 200},
{Rob1: 100}
];
Now I want to divide each item in 'productionTime' by its respective 'BusyTime' which have the same key.
For example productionTime.Rob3 should be divided by BusyTime.Rob3 and productionTime.Rob8 should be divided by BusyTime.Rob8 and so on.
How can I do this with array.find() or array.filter() in javascript/nodejs?
P.S: I know i can do it by using two nested forEach loops but that is I guess very slow
You could use a hash table and a single loop for every array.
var productionTime = [{ Rob3: 20 }, { Rob8: 100 }, { Rob4: 500 }, { Rob1: 100 }, { Rob5: 500 }];
busytime = [{ Rob4: 10 }, { Rob3: 200 }, { Rob8: 100 }, { Rob5: 200 }, { Rob1: 100 }],
hash = Object.create(null);
busytime.forEach(function (o) {
var key = Object.keys(o)[0];
hash[key] = o[key];
});
productionTime.forEach(function (o) {
var key = Object.keys(o)[0];
o[key] /= hash[key];
});
console.log(productionTime);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Convert both arrays to object using Object#assign and the spread syntax. Get the keys from one of them using Object#keys, and iterate the keys using Array#map. Create a new object for each key using shorthand property names:
const productionTime = [{"Rob3":20},{"Rob8":100},{"Rob4":500},{"Rob1":100},{"Rob5":500}];
const Busytime= [{"Rob4":10},{"Rob3":200},{"Rob8":100},{"Rob5":200},{"Rob1":100}];
// create objects from both arrays
const productionTimeObj = Object.assign({}, ...productionTime);
const busytimeObj = Object.assign({}, ...Busytime);
// get the keys from one of the objects, and iterate with map
const result = Object.keys(productionTimeObj).map((key) => ({
// create a new object with the key, and the result of the division
[key]: productionTimeObj[key] / busytimeObj[key]
}));
console.log(result);
I have severel Objects containing one sort of data:
Prices:
'btc-usd' : 2640, 'ltc-usd': 40, ...
Amount of Crypto:
'btc-usd': 2.533, 'ltc-usd': 10.42, ...
How can I take these Objects and create an Array of Objects like:
[ { name: 'Bitcoin', amount: 2.533, value: 2640, id: 'btc-usd' },
{ name: 'Litecoin', amount: 10.42, value: 40, id: 'ltc-usd' }, ...
]
Thanks a lot for your help!
You could map the keys of one of the objects to produce a new array of objects. You just have to make sure, that the key is in every of these objects.
const names = {
'btc-usd' : 'Bitcoin',
'ltc-usd': 'Litecoin',
...
}
const prices = {
'btc-usd' : 2640,
'ltc-usd': 40,
...
}
const amounts = {
'btc-usd': 2.533,
'ltc-usd': 10.42,
...
}
const cryptos = Object.keys(names).map((key, index) => ({
name: names[key],
amount: amounts[key] ,
value: prices[key]},
id: key
}));
You could use a hash map (e.g. 'btc-usd' => {name:"Bitcoin",...}) to create new objects. This hashmap can be easily converted to an array.
var input={
value:{'btc-usd' : 2640, 'ltc-usd': 40},
amount:{'btc-usd': 2.533, 'ltc-usd': 10.42},
name:{"btc-usd":"Bitcoin","ltc-usd":"Litecoin"}
};
var hash={};
for(key in input){
var values=input[key];
for(id in values){
if(!hash[id]) hash[id]={id:id};
hash[id][key]=values[id];
}
}
var output=Object.values(hash);
http://jsbin.com/fadapafaca/edit?console
Here's a generalized function, add, that accepts a field name and an object of values and maps them into a result object which can then be mapped into an array.
const amounts = {btc: 123.45, eth: 123.45};
const names = {btc: 'Bitcoin', eth: 'Etherium'};
const result = {};
const add = (field, values) => {
Object.keys(values).forEach(key => {
// lazy initialize each object in the resultset
if (!result[key]) {
result[key] = {id: key};
}
// insert the data into the field for the key
result[key][field] = values[key];
});
}
add('amount', amounts);
add('name', names);
// converts the object of results to an array and logs it
console.log(Object.keys(result).map(key => result[key]));
const prices = {
'btc-usd' : 2640,
'ltc-usd': 40
};
const amounts = {
'btc-usd': 2.533,
'ltc-usd': 10.42
};
First, create a dictionary of what each abbreviation stands for.
const dictionary = {
'btc': 'Bitcoin',
'ltc': 'Litecoin'
};
Then, populate an empty array with objects containing the relevant information. In each of these objects, the name would correspond to the relevant key within the dictionary object. At the same time, the amount and value would correspond to the relevant key within the amounts and prices objects respectively. Finally, the Id would correspond to the key itself.
const money = [];
for(let coin in prices) {
money.push({
name: dictionary[coin.substr(0, coin.indexOf('-'))],
amount: amounts[coin],
value: prices[coin],
id: coin
});
}
console.log(money);
Essentially, I want to implement the following:
var categories = [];
var products = // some array of product objects
products.map(function(value) {
if(categories.indexOf(value.Category === -1)) categories.push(value.Category);
});
As result, categories array contains unique list of product categories.
I feel that there should be a better way to do it, but nothing comes to mind.
If there isn't then probably there is no point to use map() in the first place. I could do as simple as
var categories = [];
var products = // some array of product objects
for (var i = 0; i < products.length; i++) {
if(categories.indexOf(products[i].Category === -1)) categories.push(products[i].Category);
}
UPDATE for those who insist it's a duplicate of "how to make an array unique" question. I saw that post, and for my situation I don't think it applies. I don't have an array of values that I need to make unique. I have an array of objects and I need to build an array of unique values. The difference might be subtle - but to get to the use case of that topic I would build a non-unique array and then make it unique. Seems even worse than my original solution
you can use reduce instead of map
var products = [{Category:'vegetable', price: 1}, {Category:'fruits', price: 2}];
var categories = products.reduce(function(sum, product) {
if(sum.indexOf(product.Category) === -1){
sum.push(product.Category);
}
return sum;
}, []);
Update: A solution with Array.prototype.reduce()
var products = [{ Name: 'milk', price: 2.50, Category: 'groceries' }, { Name: 'shirt', price: 10, Category: 'clothing' }, { Name: 'apples', price: 5, Category: 'groceries' }],
categories = products.reduce(function (r, a) {
if (!~r.indexOf(a.Category)) {
r.push(a.Category);
}
return r;
}, []);
document.write('<pre>' + JSON.stringify(categories, 0, 4) + '</pre>');
map all the values of the object categories out first, then use filter to dispose of the duplicates.
var products = [
{ category: 'A' },
{ category: 'B' },
{ category: 'A' },
{ category: 'D' }
];
var categories = products.map(function (e) {
return e.category;
}).filter(function (e, i, a) {
return a.indexOf(e) === i;
}); // [ "A", "B", "D" ]
DEMO
Follow the Below SO Answer:
How to get distinct values from an array of objects in JavaScript?
var flags = [], output = [], l = array.length, i;
for( i=0; i<l; i++) {
if( flags[array[i].age]) continue;
flags[array[i].age] = true;
output.push(array[i].age);
}
Suppose I have an array of objects with some sort of groupable key:
var people = [
{ 'name':'Alice', 'gender': 'female' },
{ 'name':'Bob', 'gender': 'male' },
{ 'name':'Jeremy', 'gender': 'male' },
{ 'name':'Jess', 'gender': 'female' },
{ 'name':'Seymour', 'gender': 'female' },
];
Is there a (native) function/method that can be applied to the array to 'unzip' the array into two arrays, like so:
boysAndGirls = people.[**something**]('gender');
That could result in:
{
'male': [ ... ],
'female': [ ... ]
}
or even:
[
[ {Bob, ...}, {Jeremy, ...}, {Seymour, ...} ], // 'males' array
[ {Alice, ...}, {Jess, ...} ] // 'female' array
]
I could write this algorithm myself, but I really just want to know if there is a native array method -- or one that might exist in another language that could be polyfilled in?
const groupByAge = users.reduce((p,c) =>{
const genKey = Math.floor(c.age/10);
const key = `${genKey}0- ${genKey}9`;
if(!p[key]){
p[key] =[];
}
p[key].push(c);
return p;
}, {})
console.log(groupByAge);
There is no such method in JavaScript. Ruby has it in Enumerator#group_by:
people.group_by { |person| person['gender'] }
and it is easy enough to write in JavaScript as well. In fact, some libraries have it already, e.g. Lodash.
_.groupBy(people, function(person) {
return person['gender'];
});
If you write it yourself, you can customise it a bit:
function groupByProp(array, prop) {
var result = {};
array.forEach(function(item) {
var val = item[prop];
if (!result[val]) result[val] = [item];
else result[val].push(item);
});
return result;
}
groupByProp(people, 'gender');
There is not a native Javascript function for this but you can use the following code:
var originalArray = [1,2,3,4,5,6,7,8,9];
var splitArray = function (arr, size) {
var arr2 = arr.slice(0),
arrays = [];
while (arr2.length > 0) {
arrays.push(arr2.splice(0, size));
}
return arrays;
}
splitArrays = splitArray(originalArray, 2);
console.log(splitArrays);
The nearest thing I can think of off the top of my head for a native solution is to use reduce. It's not as simple as what you are looking for but it works:
var boysAndGirls = people.reduce(function(obj, item) {
obj[item.gender].push(item.name);
return obj;
}, {male: [], female: []});