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());
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}
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.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);
});