Arrays to objects - javascript

I have this question and I cannot find the answer:
Create a function called firstAndLast which takes an array and returns an object which has one property. The key of that property should be the first array element and it's value should be the last element in the array. Example:
firstAndLast(["queen", "referee", "cat", "beyonce"]) should return {queen: "beyonce"}.

Some diversity of approaches (admittedly esoteric, but fun!):
function firstAndLast(a, o){
return !(o = {}, o[a.shift()] = a.pop()) || o;
}
console.log(firstAndLast([1,2,3,4,5]));
console.log(firstAndLast(['a','to','z']));
https://jsfiddle.net/brtsbLp1/
And, of course:
function firstAndLast(a, o){
return !(o = o || {}, o[a.shift()] = a.pop()) || o;
}
console.log(firstAndLast(['a','to','z']));
console.log(firstAndLast(['a','to','z'], {a:'nother',obj:'ect'}));
https://jsfiddle.net/brtsbLp1/1/
Another fun one:
function firstAndLast(a){
return JSON.parse('{"'+a.shift()+'":"'+a.pop()+'"}');
}
https://jsfiddle.net/brtsbLp1/2/
That last one will choke on the first being a number (since labels aren't allowed to be numbers only), plus other issues in general. But this should give some food for thought. The other answers are a bit more obvious.

you can specify the key with []
function firstAndLast(arr){
let o = {};
o[arr[0]] = arr[arr.length - 1]; // the key is the first elem, the value the last elem of the array
return o;
}
let a = [1,2,3,4,5]
let b = firstAndLast(a)

function firstAndLast(arr){
var obj = {
}
var length = arr.length;
obj[arr [0]]=arr[length-1] //{queen:beyonce}
return obj
}
var arr = ["queen", "referee", "cat", "beyonce"]
var output = firstAndLast(arr) //{queen:beyonce}

Related

Transform array of objects in Jacascript [duplicate]

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;
}

Javascript number of object by different property values in array

Best way to count the number of objects in a array with different object property p values.
function([{"p":"a"},{"p":"b"},{"p":"a"}]){
// some code
}
// in this case return 2
You can use Array.prototype.filter() to keep values that you want. In this case, you must create a variable temp for storing duplicate values and also within the filter function returns true if it does not exist in case. So you have a new array of unique values.
var arr = [{"p":"a"},{"p":"b"},{"p":"a"}], temp = [];
var arrUniques = arr.filter(function(obj){
return temp.indexOf(obj.p) === -1 ? !!temp.push(obj.p) : false
});
alert(arrUniques.length)
With a Map:
var props = new Map();
for (var i = 0; i < array.length; i++) {
var prop = array[i].p,
count = props.get(prop) || 0;
props.set(prop, count + 1);
}
var size = props.size;
If your properties can be safely casted to strings, you can use a common object:
var props = {};
...
var size = Object.keys(props).length;
Otherwise, Map is your answer.
function getUniquePropertyCount(a, p) {
return a.reduce(function (res, el) {
!~res.indexOf(el[p]) && res.push(el[p]);
return res;
}, []).length;
}
document.write(getUniquePropertyCount([{ "p": "a" }, { "p": "b" }, { "p": "a" }], 'p'));
I suppose this is one of those questions where if you ask four programmers, you'll get five answers.
The other answers so far show some interesting approaches. I would watch out for browser compatibility; for example Map() is only available in the newest browsers, not in IE 10 or prior.
So here's one more solution. It's a bit more code, but it's pretty easy to understand, and it works in every browser:
function countUniqueProperties( key, array ) {
var count = 0, values = {};
for( var i = 0; i < array.length; ++i ) {
var value = array[i][key];
if( ! Object.prototype.hasOwnProperty.call( values, value) ) {
++count;
values[value] = true;
}
}
return count;
}
countUniqueProperties( 'p', [ {p:'a'}, {p:'b'}, {p:'a'} ] );
The one complicated part here is the Object.prototype.hasOwnProperty.call(values,value). You could just use values.hasOwnProperty(value), but that would fail if one of your property values was the string "hasOwnProperty":
countUniqueProperties( 'p', [ {p:'a'}, {p:'hasOwnProperty'}, {p:'a'} ] );
Using the longer form avoids this issue.
lodash is nice for things like this.
Use
_.uniq([{"p":"a"},{"p":"b"},{"p":"a"}]).length
and it'll return 2.

Javascript: how to dynamically create nested objects INCLUDING ARRAYS using object names given by an array

Very similar to this question:
Javascript: how to dynamically create nested objects using object names given by an array
Instead of calling
assign(obj, keyPath, value)
example of usage of the previously answer:
var accountinfo = {}
assign(accountinfo, ["name", "addressinfo", "zipcode"], "90210");
That will output:
accountinfo = {name: "", addressinfo: {zipcode:"90210"}};
Now, I'd like to support arrays... in the above example, I'd like to support multiple addressinfo per account. I'd like to say:
assign(accountinfo, ["name", "addressinfo[1]", "zipcode"], "90210");
The result would be:
accountinfo = {name: "", addressinfo: [{},{zipcode:"90210"}]}
var regex = /\[([0-9]+)\]/ will show me the # inside the brackets, but I'm not sure how I'd have to iterate through each element in the array to make sure it exists (and create it if it doesn't).. and the difficult part, support this for each array element submitted as part of the function (I'd like to say :
assign(accountinfo, ["family", "name[3]", "addressinfo[1]", "zipcode"], "90210");
Edit:
Figured it out.
function assign(obj, keyPath, value) {
keyPath = keyPath.split(‘.’);
lastKeyIndex = keyPath.length - 1;
var re = /^(.+?)\[*(\d+)*\]*$/;
for (var i = 0; i < lastKeyIndex; i++) {
key = keyPath[i];
var ind;
var middle = re.exec(key);
key = middle[1];
ind = middle[2];
if (ind) {
if (!(obj[key]))
obj[key] = [];
if (!(obj[key][ind]))
obj[key][ind] = {};
}
if (!(key in obj))
obj[key] = {};
if (ind)
obj = obj[key][ind];
else
obj = obj[key];
}
obj[keyPath[lastKeyIndex]] = value;
}

how to manipulate array object and create new array

I have js array as seen below:
var names = [{name:"high",id:1},{name:"high",id:2},
{name:"low",id:1}, {name:"low",id:2},{name:"medium",id:1},{name:"medium",id:2}];
I need to create another array out of this like this.
var newArr=[{name:high,items:[1,2]},{name:low,items:[1,2]},{name:medium,items:[1,2]}];
Please suggest me how to do that.
Underscorejs based solution
var obj = {};
_.each(names, function (e) {
var o = obj[e.name];
if (o) {
o.items.push(e.id);
} else {
o = {name: e.name, items: [e.id]};
}
obj[e.name] = o;
});
var result = _.map(obj, function (e) {return e;});
Pure js
var obj = {};
for (var i = 0; i < names.length; i++) {
var e = names[i];
var o = obj[e.name];
if (o) {
o.items.push(e.id);
} else {
o = {name: e.name, items: [e.id]};
}
obj[e.name] = o;
}
var result = [];
for (var k in obj) {
if (obj.hasOwnProperty(k)) {
result.push(obj[k]);
}
};
Here is a simple to understand solution without external library.
var newArr = []
for ( var i in names ) {
var exists = findItemInArray(names[i].name,newArr);
if(exists) { // Another item with same name was added to newArray
var items = exists.items.push(names[i].id); // We add the id to existing item
} else { // No other item with same name was added to newArray
var newItem = {name:names[i].name, items:names[i].id};
newArr.push(newItem);
}
}
And I made this function to return the item if it already exists in newArray
function findItemInArray(name,array){
for(var i in array){
if(array[i].name === name){
return array[i];
}
return null;
}
Here's a solution that uses no external libraries:
/**
* Add the given object to the given set.
*
* #param {object} theSet The set to add this object to.
* #param {object} theObject The object to add to the set.
*
* #return {object} theSet, with theObject added to it.
*
* #note Assumes that theObject.name should be the key,
* while theObject.id should go into the value array.
* #note This is an Array.prototype.reduce() callback.
*/
function collect(theSet, theObject) {
if (theSet.hasOwnProperty(theObject.name)) {
theSet[theObject.name].push(theObject.id);
} else {
theSet[theObject.name] = [theObject.id];
}
return theSet;
}
var names = [{name:"high",id:5},{name:"high",id:6},
{name:"low",id:1}, {name:"low",id:2},{name:"medium",id:3},{name:"medium",id:4}],
combinedSet = names.reduce(collect, {}), // This is Step 1
final = [],
key;
// This is Step 2
for (key in combinedSet) {
if (combinedSet.hasOwnProperty(key)) {
final.push(
{
"name" : key,
"items": combinedSet[key]
}
);
}
}
The first step is to group the IDs under the object names. I use Array.prototype.reduce to do this, with the callback collect. The result of that transformation goes into the combinedSet variable.
The second step is to take the set we made in Step 1 and turn it into the final array: make objects using the set's keys as the name member, and use its values as the items member. I can't use reduce like I could before, so I go with a simple for loop. Note that I wrapped things up with a hasOwnProperty check, to guard against the possibility that someone has modified Object.prototype; if I didn't do this, then there might be more items in the set that I hadn't put there, and that would introduce bugs.
You are looking for a grouping function. Try underscoreJs groupBy:
jsFiddle
var names = [{name:"high",id:1},{name:"high",id:2}, {name:"low",id:1}, {name:"low",id:2},{name:"medium",id:1},{name:"medium",id:2}];
console.debug(_.groupBy(names, 'name'));
// Object {high: Array[2], low: Array[2], medium: Array[2]}, where each item in the nested arrays refers to the original object

Returning only certain properties from an array of objects in Javascript [duplicate]

This question already has answers here:
From an array of objects, extract value of a property as array
(24 answers)
Closed 8 years ago.
If I have an object such that
var object = function(key,text)
{
this.key = key;
this.text = text;
}
And create an array of these objects
var objArray = [];
objArray[0] = new object('key1','blank');
objArray[1] = new object('key2','exampletext');
objArray[2] = new object('key3','moretext');
is there a way that I can retrieve only one of the properties of all of the objects in the array? For example:
var keyArray = objArray["key"];
The above example doesn't return set keyArray to anything, but I was hoping it would be set to something like this:
keyArray = [
'key1',
'key2',
'key3']
Does anyone know of a way to do this without iterating through the objArray and manually copying each key property to the key array?
This is easily done with the Array.prototype.map() function:
var keyArray = objArray.map(function(item) { return item["key"]; });
If you are going to do this often, you could write a function that abstracts away the map:
function pluck(array, key) {
return array.map(function(item) { return item[key]; });
}
In fact, the Underscore library has a built-in function called pluck that does exactly that.
var object = function(key,text) {
this.key = key;
this.text = text;
}
var objArray = [];
objArray[0] = new object('key1','blank');
objArray[1] = new object('key2','exampletext');
objArray[2] = new object('key3','moretext');
var keys = objArray.map(function(o,i) {
return o.key;
});
console.log(keys); // ["key1", "key2", "key3"]
JS Bin Example
http://jsbin.com/vamey/1/edit
Note that older browsers may not support map but you can easily do this with a for loop:
var keys = [];
for (var i = 0; i < objArray.length; i++) {
keys.push(objArray[i].key);
}
JS Bin Example
http://jsbin.com/redis/1/edit
You would want to do something like this:
objArray.map(function (obj) { return obj.key; });
Here is a JSFiddle to demo: http://jsfiddle.net/Q7Cb3/
If you need older browser support, you can use your own method:
JSFiddle demo: http://jsfiddle.net/Q7Cb3/1/
function map (arr, func) {
var i = arr.length;
arr = arr.slice();
while (i--) arr[i] = func(arr[i]);
return arr;
}
Well something has to iterate through the elements of the array. You can use .map() to make it look nice:
var keys = objArray.map(function(o) { return o.key; });
You could make a function to generate a function to retrieve a particular key:
function plucker(prop) {
return function(o) {
return o[prop];
};
}
Then:
var keys = objArray.map(plucker("key"));
Really "objArray" is an array that have 3 objects inside, if you want list of keys, you can try this:
var keys = [];
for(a in objArray) {
keys.push(objArray[a].key);
}
You have in var keys, the three keys.
Hope that helps! :)

Categories

Resources