How to convert array into object? - javascript

I have this array, var arr = [0, 1, 2]
and I would like to convert it into an object like this,
Object{
data: [0, 1, 2]
}
How would I get the desired output using a function perhaps? Thanks.

Just create an object and assign the array to one it it's properties:
var arr = [0, 1, 2];
var obj = {
data : arr
};
Or if you have an existing object, you can add the array by name:
obj['data'] = arr;
Or dot notation:
obj.data = arr;
You should be aware that these are all copying the array by reference, so any updates you make to the arr variable will update obj.data as well. If you want to copy by value, you could do something like:
var obj = {
data: arr.slice(0)
};
See this JSFiddle for an example of copying by reference versus copying by value. You could read the answer to this question for more information about copying by value vs copying by reference.

You can do this very easily like this var obj = {data:arr}; However I think you should consider what purpose you are using the object for. An array is technically already a javascript object so you may not even need to do this

It's quite easy you just need a factory for it.
function arrayToObjectTransformationFactory($array, $transformationTransportProtocol){
return function($array){
if ( !Array.prototype.forEach ) {
Array.prototype.forEach = function(fn, scope) {
for(var i = 0, len = this.length; i < len; ++i) {
fn.call(scope, this[i], i, this);
}
};
}
$array.forEach($transformationTransportProtocol)
return { "data": $array };
}($array);
}
arrayToObjectTransformationFactory([0, 1, 2], function($element, $index, $array){
var quux = [];
quux.push($array[$index]);
});
Should work cross browser and with jQuery too.

Related

JS How to make a new method to an Array using prototype but with a function that takes no parameters

I want to extend the Array with a new method called square() which returns a new array with all the numbers squared. I tried making it but I can't figure out a way in which the function does not take any parameters like the default JS Array methods. For example array.reverse() returns the array reversed it doesn't take the array as the parameter, like this: array.reverse(array)
This is my code:
Array.prototype.square = function(Array){
let a = []
for (let num of Array){
a.push(num**2)
}
return a
}
You can use the this keyword inside of your function and it will refer to the array calling it.
Array.prototype.square = function() {
return this.map(number => number ** 2)
}
let test = [1, 2, 3]
console.log(test.square())
You were on the right track, it can be easily done like this:
Array.prototype.square = function () {
return this.map((number) => number * number)
}
let a = [1, 2]; // sample array
console.log(a.square()); // prints [1, 4]
I have used map, which makes the process extremely easy. Refer to this for more information: Array Map Function
for the record...
(the name of this kind of added method is called a wrapper)
/* --- Array.square wrapper--- */
if (!Array.prototype.square) // check that the square method does not already exist
{
Array.prototype.square = function(){ return this.map(x=>x**2) }
}
let arr1 = [1,2,3,5,7]
, arr2 = arr1.square()
;
console.log('arr1 ->', JSON.stringify( arr1 ))
console.log('arr2 ->', JSON.stringify( arr2 ))
When you add methods to a prototype the object/array will always be the this context. So you can simply loop over this.
(Aside: it's often good to check that the method doesn't already exist on the prototype which is why I included that code too.)
if (!('square' in Array.prototype)) {
Array.prototype.square = function() {
const arr = [];
for (let i = 0; i < this.length; i++) {
arr.push(this[i] ** 2);
}
return arr;
}
}
console.log([1, 2, 3].square());
Or, more simply, use map to return a new array.
if (!('square' in Array.prototype)) {
Array.prototype.square = function() {
return this.map(el => el ** 2);
}
}
console.log([1, 2, 3].square());

Array of objects: accessing an object's value without iterating through the array

I have an array of similarly structured objects:
var my_arr = [{property1: some_value, property2: another_value}, {}, {}, ...];
Currently, to find the object containing a target value, I iterate through each element of the array:
var my_obj, target_value;
for (let obj_in_arr of my_arr) {
if (obj_in_arr.property1 === target_value) {
my_obj = obj_in_arr;
break;
}
}
Is there a faster way? How can I access the object with the target value directly, without resorting to iteration?
If you prepopulate a new Map all subsequent searches will be in O(1)
const objMap = new Map()
for (let obj of my_arr) {
objMap.set(obj.property1, obj)
}
function getObject(target, map) {
return map.get(target)
}
I think you need to iterate the array anyway, but you can try _.findIndex of underscore.js
http://underscorejs.org/#findIndex
If you only need to find a value once, then iteration is really the only way.
If you will want to find many values in the array, you could create an object keyed on your target property to serve as a lookup table:
var lookup = {};
for (var i = 0; i < my_arr.length; i++) {
lookup[my_arr[i].property1] = my_arr[i];
}
That front loads some work, but could save you time ultimately if you have many lookups to make.
Lookups would be as simple as:
my_obj = lookup[target_value];
If you have access to es2015 you could make your lookup table generation a little more concise:
const lookup = my_arr.reduce((m, v) => (m[v.property1] = v, m), {});
this will still iterate through the array but you could use the native js find function.
const objArray = [{ val: 1}, { val: 2}];
const targetObj = objArray.find((obj) => obj.val == 2 ) // { val: 2}

about optimizing for-in statement

I read an article named Optimization killers, and in 5.2.3. The object contains enumerable array indices, It says :
Workaround: Always use Object.keys and iterate over the array with for loop. If you truly need all properties from entire prototype chain, make an isolated helper function:
function inheritedKeys(obj) {
var ret = [];
for(var key in obj) {
ret.push(key);
}
return ret;
}
I don't understand what it means.
In the above code, there is still a for...in, so function inheritedKeys can't be optimized, how can it be an isolated helper function?
That's just an example on how to get keys from an object doing it with the for in loop.
He actually tells you that in order to make it faster you should use Object.keys when you want to get keys of an object.
Here's the test performance.
http://jsperf.com/forintest
So DON'T use this to retrieve object keys
function inheritedKeys(obj) {
var ret = [];
for(var key in obj) {
ret.push(key);
}
return ret;
}
var myobject= {"1":"a","2":"b"};
var calculation = inheritedKeys(myobject);
Use this instead it's more clean simple to read and faster
var myobject= {"1":"a","2":"b"};
var calculation = Object.keys(myobject);
Here's a test comparing for in using with array and a normal for loop.
http://jsperf.com/forinarray
You can see that the for loop is way faster.
DON'T use this
function iteratesOverArray() {
var arr = [1, 2, 3];
var newArr = [];
for (var index in arr) {
newArr.push(index);
}
return newArr;
}
var arr = iteratesOverArray();
Use this instead
function iteratesOverArray() {
var arr = [1, 2, 3];
var newArr = [];
for (var i=0,l=arr.length-1;i<=l;i++) {
newArr.push(i);
}
return newArr;
}
var arr = iteratesOverArray();

How does the Javascript Array Push code work internally

What is the internal code logic for Push and Pop methods in javascript..?? How does Push method stores the values in Array.
The push and pop methods are intentionally generic, they only rely on the existance of a length property, and that they can add and remove properties.
The push method will read the length property, add a property with that name, and increase the length. Basically:
function push(value) {
var len = this.length;
this[len] = value;
len++;
this.length = len;
return len;
}
The pop method will read the length property, decrease it, get the property with that name and remove the property. Basically:
function pop() {
var len = this.length - 1;
var value = this[len];
this.length = len;
delete this[len];
return value;
}
The actual implementations are a bit more complex, as they support for example multiple parameters for the push method, and some more error checks. There might also implement special optimised code for when the object is actually an array, but then the generic code is still there for other objects.
The methods are intentionally generic so that they can be used on objects that aren't actually arrays. You can make your own object that supports them by just having a length property:
var o = {
length: 0,
push: Array.prototype.push,
pop: Array.prototype.pop
};
o.push(1);
var one = o.pop();
Demo: http://jsfiddle.net/Guffa/9r4gavzb/
We can try some tests and test behavior:
const arr1 = []
const { push: push1 } = arr
const arr2 = []
const { push: push2 } = arr
console.log(push1 === push2) // true
console.log(push1 === Array.prototype.push) // true
push1(1) // TypeError: Cannot convert undefined or null to object
push1.call(arr1, 1) // arr1: [1], arr2: []
push2.call(arr1, 2) // arr1: [1, 2], arr2: []
push1.bind(arr2)(1) // arr1: [1, 2], arr2: [1]
push.call(arr2, 2)
And we can say that push method uses this under the hood...

jQuery function to get all unique elements from an array?

jQuery.unique lets you get unique elements of an array, but the docs say the function is mostly for internal use and only operates on DOM elements. Another SO response said the unique() function worked on numbers, but that this use case is not necessarily future proof because it's not explicitly stated in the docs.
Given this, is there a "standard" jQuery function for accessing only the unique values — specifically, primitives like integers — in an array? (Obviously, we can construct a loop with the each() function, but we are new to jQuery and would like to know if there is a dedicated jQuery function for this.)
You can use array.filter to return the first item of each distinct value-
var a = [ 1, 5, 1, 6, 4, 5, 2, 5, 4, 3, 1, 2, 6, 6, 3, 3, 2, 4 ];
var unique = a.filter(function(itm, i, a) {
return i == a.indexOf(itm);
});
console.log(unique);
If supporting IE8 and below is primary, don't use the unsupported filter method.
Otherwise,
if (!Array.prototype.filter) {
Array.prototype.filter = function(fun, scope) {
var T = this, A = [], i = 0, itm, L = T.length;
if (typeof fun == 'function') {
while(i < L) {
if (i in T) {
itm = T[i];
if (fun.call(scope, itm, i, T)) A[A.length] = itm;
}
++i;
}
}
return A;
}
}
Just use this code as the basis of a simple JQuery plugin.
$.extend({
distinct : function(anArray) {
var result = [];
$.each(anArray, function(i,v){
if ($.inArray(v, result) == -1) result.push(v);
});
return result;
}
});
Use as so:
$.distinct([0,1,2,2,3]);
Based on #kennebec's answer, but fixed for IE8 and below by using jQuery wrappers around the array to provide missing Array functions filter and indexOf:
$.makeArray() wrapper might not be absolutely needed, but you'll get odd results if you omit this wrapper and JSON.stringify the result otherwise.
var a = [1,5,1,6,4,5,2,5,4,3,1,2,6,6,3,3,2,4];
// note: jQuery's filter params are opposite of javascript's native implementation :(
var unique = $.makeArray($(a).filter(function(i,itm){
// note: 'index', not 'indexOf'
return i == $(a).index(itm);
}));
// unique: [1, 5, 6, 4, 2, 3]
I would use underscore.js, which provides a uniq method that does what you want.
// for numbers
a = [1,3,2,4,5,6,7,8, 1,1,4,5,6]
$.unique(a)
[7, 6, 1, 8, 3, 2, 5, 4]
// for string
a = ["a", "a", "b"]
$.unique(a)
["b", "a"]
And for dom elements there is no example is needed here I guess because you already know that!
Here is the jsfiddle link of live example:
http://jsfiddle.net/3BtMc/4/
Paul Irish has a "Duck Punching" method (see example 2) that modifies jQuery's $.unique() method to return unique elements of any type:
(function($){
var _old = $.unique;
$.unique = function(arr){
// do the default behavior only if we got an array of elements
if (!!arr[0].nodeType){
return _old.apply(this,arguments);
} else {
// reduce the array to contain no dupes via grep/inArray
return $.grep(arr,function(v,k){
return $.inArray(v,arr) === k;
});
}
};
})(jQuery);
Walk the array and push items into a hash as you come across them. Cross-reference the hash for each new element.
Note that this will ONLY work properly for primitives (strings, numbers, null, undefined, NaN) and a few objects that serialize to the same thing (functions, strings, dates, possibly arrays depending on content). Hashes in this will collide as they all serialize to the same thing, e.g. "[object Object]"
Array.prototype.distinct = function(){
var map = {}, out = [];
for(var i=0, l=this.length; i<l; i++){
if(map[this[i]]){ continue; }
out.push(this[i]);
map[this[i]] = 1;
}
return out;
}
There's also no reason you can't use jQuery.unique. The only thing I don't like about it is that it destroys the ordering of your array. Here's the exact code for it if you're interested:
Sizzle.uniqueSort = function(results){
if ( sortOrder ) {
hasDuplicate = baseHasDuplicate;
results.sort(sortOrder);
if ( hasDuplicate ) {
for ( var i = 1; i < results.length; i++ ) {
if ( results[i] === results[i-1] ) {
results.splice(i--, 1);
}
}
}
}
return results;
};
this is js1568's solution, modified to work on a generic array of objects, like:
var genericObject=[
{genProp:'this is a string',randomInt:10,isBoolean:false},
{genProp:'this is another string',randomInt:20,isBoolean:false},
{genProp:'this is a string',randomInt:10,isBoolean:true},
{genProp:'this is another string',randomInt:30,isBoolean:false},
{genProp:'this is a string',randomInt:40,isBoolean:true},
{genProp:'i like strings',randomInt:60,isBoolean:true},
{genProp:'this is a string',randomInt:70,isBoolean:true},
{genProp:'this string is unique',randomInt:50,isBoolean:true},
{genProp:'this is a string',randomInt:50,isBoolean:false},
{genProp:'i like strings',randomInt:70,isBoolean:false}
]
It accepts one more parameter called propertyName, guess! :)
$.extend({
distinctObj:function(obj,propertyName) {
var result = [];
$.each(obj,function(i,v){
var prop=eval("v."+propertyName);
if ($.inArray(prop, result) == -1) result.push(prop);
});
return result;
}
});
so, if you need to extract a list of unique values for a given property, for example the values used for randomInt property, use this:
$.distinctObj(genericObject,'genProp');
it returns an array like this:
["this is a string", "this is another string", "i like strings", "this string is unique"]
function array_unique(array) {
var unique = [];
for ( var i = 0 ; i < array.length ; ++i ) {
if ( unique.indexOf(array[i]) == -1 )
unique.push(array[i]);
}
return unique;
}
Plain JavaScript modern solution if you don't need IE support (Array.from is not supported in IE).
You can use combination of Set and Array.from.
const arr = [1, 1, 11, 2, 4, 2, 5, 3, 1];
const set = new Set(arr);
const uniqueArr = Array.from(set);
console.log(uniqueArr);
The Set object lets you store unique values of any type, whether primitive values or object references.
The Array.from() method creates a new Array instance from an array-like or iterable object.
Also Array.from() can be replaced with spread operator.
const arr = [1, 1, 11, 2, 4, 2, 5, 3, 1];
const set = new Set(arr);
const uniqueArr = [...set];
console.log(uniqueArr);
You can use a jQuery plugin called Array Utilities to get an array of unique items.
It can be done like this:
var distinctArray = $.distinct([1, 2, 2, 3])
distinctArray = [1,2,3]
If anyone is using knockoutjs try:
ko.utils.arrayGetDistinctValues()
BTW have look at all ko.utils.array* utilities.
As of jquery 3.0 you can use $.uniqueSort(ARRAY)
Example
array = ["1","2","1","2"]
$.uniqueSort(array)
=> ["1", "2"]
If you need to support IE 8 or earlier, you can use jQuery to accomplish this.
var a = [1,2,2,3,4,3,5];
var unique = $.grep(a, function (item, index) {
return index === $.inArray(item, a);
});

Categories