Arguments Object - javascript

i'm currently learning js and need to pass a test, every requirement checks out besides "should work on an arguments object".
So I need to use arguments[0]or[1], its also necessary for me to check if the array is an array. Issue here is that for some reason the Array.isArray() part of the code turns my "should work on an arguments object" requirement false, even though I used arguments[0].
please try to ignore the rest of the code, there are also other requirements set. I know they seem kind of unnecessary to include.
this is my code:
function (array, n) {
var resultArray = [];if (typeof arguments[1] !== "number" || arguments[1] == 0 || arguments[1] < 0){
resultArray.push.call(resultArray, arguments[0][0])
return resultArray
}
else if (arguments[1] > arguments[0].length){
return arguments[0] && array
} else {
return resultArray;
}
};

That's because the requirements expects you use somewhere the variable argument array. Instead you use arguments[0].
So use the first over the latter.
Likewise, use n instead of arguments[1]

You can use Array.prototype.slice function simply
const first = (array = [], n = 1) =>
Array.isArray(array) ? array.slice(0, array.length >= n ? n : 1) : [];
If n > array.length this will return the whole array.

Try this:
if (!window[atob('QXJyYXk=')][atob('aXNBcnJheQ==')](arguments[0])) return [];

Related

How to use Javascript array.find() with two conditions?

I need to check if any object in an array of objects has a type: a AND if another has a type: b
I initially did this:
const myObjects = objs.filter(attr => attr.type === 'a' || attr.type === 'b');
But the code review complained that filter will keep going through the entire array, when we just need to know if any single object meets either criteria.
I wanted to use array.find() but this only works for a single condition.
Is there anyway to do this without using a for loop?
you can pass two condition as given below
[7,5,11,6,3,19].find(attr => {
return (attr > 100 || attr %2===0);
});
6
[7,5,102,6,3,19].find(attr => {
return (attr > 100 || attr %2===0);
});
102
Updated answer:
It's not possible to shortcircuit js's builtin functions that does what you want, so you will have to use some kind of loop:
let a;
let b;
for (const elm of objs) {
if (!a && elm === 'a') {
a = elm;
}
if (!b && elm === 'b') {
b = elm;
}
const done = a && b;
if (done) break;
}
Also you should consider if you can record a and b when producing the array if that's possible.
Oiginal answer:
`find` works just like `filter` where it takes a predicate, returns the first element that the predicate returns `true`.
If I understood your question correctly, you can just replace the `filter` with `find` and it will return at the first occurance:
const myObject = objs.find(attr => attr.type === 'a' || attr.type === 'b');
Also notice your provided snippet is wrong for what you described: `filter` returns an array but you only wanted one element. so you should add `[0]` to the filter expression if you want to use it.

JS: Handle with find() property undefined

I have a method which returns a value from an element in the array. Not all the elements have the property I want to return. I would like to do this function with one line using the method find(). I've tried this way to solve it:
getExecsFromTour(tourId){
return this.repInfo.find(el => el.id == tourId ).execs || [];
}
But the elements which don't contain the property execs return an error of undefined.
To solve it, I had to store the result in a local variable:
getExecsFromTour(tourId){
let items = this.repInfo.find(el => el.id == tourId);
return items != undefined ? items.execs : [];
}
But I would like to know if I am missing something and this function can be achieved with one sentence.
You seem to have the general idea, Array.prototype.find will search the array for the first element which, when used as an argument of the callback, will have the callback return a truthy value. If nothing is found, it returns undefined.
Your code should work, but yes, one way to do it in one line (if you want) is to use:
getExecsFromTour(tourId){
return (this.repInfo.find(el => el.id == tourId) || {}).execs || [];
}
If Array.prototype.find returns undefined, the first inner parenthetical expression will be evaluated to empty object, which can attempt (and fail) to access the .execs key without a TypeError, which will also evaluate to undefined, in which case the function returns empty array, which is what your code above does.
EDIT: Someone commented this solution already, lol, but as the comments say, nothing wrong with keeping it multiline (more readable that way).
what about
getExecsFromTour(tourId){
return this.repInfo.find(el => 'execs' in el && el.id == tourId ).execs || [];
}
...
EDITED
var a = [{execs : 1, id:4}, {id:5}];
function getExecsFromTour(tourId, x){
return (x = a.find(el => 'execs' in el && el.id == tourId )) ? x.execs : [];
}
this time at least I ran it couple of times

How to check - $scope.students = []; - in JavaScript - Angular JS [duplicate]

When the page is loading for the first time, I need to check if there is an image in image_array and load the last image.
Otherwise, I disable the preview buttons, alert the user to push new image button and create an empty array to put the images;
The problem is that image_array in the else fires all time. If an array exists - it just overrides it, but alert doesn't work.
if(image_array.length > 0)
$('#images').append('<img src="'+image_array[image_array.length-1]+'" class="images" id="1" />');
else{
$('#prev_image').attr('disabled', 'true');
$('#next_image').attr('disabled', 'true');
alert('Please get new image');
var image_array = [];
}
UPDATE
Before loading html, I have something like this:
<?php if(count($images) != 0): ?>
<script type="text/javascript">
<?php echo "image_array = ".json_encode($images);?>
</script>
<?php endif; ?>
if (typeof image_array !== 'undefined' && image_array.length > 0) {
// the array is defined and has at least one element
}
Your problem may be happening due to a mix of implicit global variables and variable hoisting. Make sure you use var whenever declaring a variable:
<?php echo "var image_array = ".json_encode($images);?>
// add var ^^^ here
And then make sure you never accidently redeclare that variable later:
else {
...
image_array = []; // no var here
}
To check if an array is either empty or not
A modern way, ES5+:
if (Array.isArray(array) && array.length) {
// array exists and is not empty
}
An old-school way:
typeof array != "undefined"
&& array != null
&& array.length != null
&& array.length > 0
A compact way:
if (typeof array != "undefined" && array != null && array.length != null && array.length > 0) {
// array exists and is not empty
}
A CoffeeScript way:
if array?.length > 0
Why?
Case Undefined
Undefined variable is a variable that you haven't assigned anything to it yet.
let array = new Array(); // "array" !== "array"
typeof array == "undefined"; // => true
Case Null
Generally speaking, null is state of lacking a value. For example a variable is null when you missed or failed to retrieve some data.
array = searchData(); // can't find anything
array == null; // => true
Case Not an Array
Javascript has a dynamic type system. This means we can't guarantee what type of object a variable holds. There is a chance that we're not talking to an instance of Array.
supposedToBeArray = new SomeObject();
typeof supposedToBeArray.length; // => "undefined"
array = new Array();
typeof array.length; // => "number"
Case Empty Array
Now since we tested all other possibilities, we're talking to an instance of Array. In order to make sure it's not empty, we ask about number of elements it's holding, and making sure it has more than zero elements.
firstArray = [];
firstArray.length > 0; // => false
secondArray = [1,2,3];
secondArray.length > 0; // => true
How about (ECMA 5.1):
if(Array.isArray(image_array) && image_array.length){
// array exists and is not empty
}
This is what I use. The first condition covers truthy, which has both null and undefined. Second condition checks for an empty array.
if(arrayName && arrayName.length > 0){
//do something.
}
or thanks to tsemer's comment I added a second version
if(arrayName && arrayName.length)
Then I made a test for the second condition, using Scratchpad in Firefox:
var array1;
var array2 = [];
var array3 = ["one", "two", "three"];
var array4 = null;
console.log(array1);
console.log(array2);
console.log(array3);
console.log(array4);
if (array1 && array1.length) {
console.log("array1! has a value!");
}
if (array2 && array2.length) {
console.log("array2! has a value!");
}
if (array3 && array3.length) {
console.log("array3! has a value!");
}
if (array4 && array4.length) {
console.log("array4! has a value!");
}
which also proves that if(array2 && array2.length) and if(array2 && array2.length > 0) are exactly doing the same
optional chaining
As optional chaining proposal reached stage 4 and is getting wider support, there is a very elegant way to do this
if(image_array?.length){
// image_array is defined and has at least one element
}
You should use:
if (image_array !== undefined && image_array.length > 0)
If you want to test whether the image array variable had been defined you can do it like this
if(typeof image_array === 'undefined') {
// it is not defined yet
} else if (image_array.length > 0) {
// you have a greater than zero length array
}
JavaScript
( typeof(myArray) !== 'undefined' && Array.isArray(myArray) && myArray.length > 0 )
Lodash & Underscore
( _.isArray(myArray) && myArray.length > 0 )
You can use jQuery's isEmptyObject() to check whether the array contains elements or not.
var testArray=[1,2,3,4,5];
var testArray1=[];
console.log(jQuery.isEmptyObject(testArray)); //false
console.log(jQuery.isEmptyObject(testArray1)); //true
Source: https://api.jquery.com/jQuery.isEmptyObject/
Using undescore or lodash:
_.isArray(image_array) && !_.isEmpty(image_array)
A simple way that doesn't result in exceptions if not exist and convert to boolean:
!!array
Example:
if (!!arr) {
// array exists
}
How about this ? checking for length of undefined array may throw exception.
if(image_array){
//array exists
if(image_array.length){
//array has length greater than zero
}
}
The best is to check like:
let someArray: string[] = [];
let hasAny1: boolean = !!someArray && !!someArray.length;
let hasAny2: boolean = !!someArray && someArray.length > 0; //or like this
console.log("And now on empty......", hasAny1, hasAny2);
See full samples list:
I come across this issue quite a lot in Javascript. For me the best way to do it is to put a very broad check before checking for length. I saw some other solutions in this Q&A, but I wanted to be able to check for either null or undefined or any other false value.
if(!array || array.length == 0){
console.log("Array is either empty or does not exist")
}
This will first check for undefined, null, or other false values. If any of those are true, it will complete the boolean as this is an OR. Then the more risky check of array.length, which could error us if array is undefined, can be checked. This will never be reached if array is undefined or null, so the ordering of conditions is very important.
If you do not have a variable declared as array you can create a check:
if(x && x.constructor==Array && x.length){
console.log("is array and filed");
}else{
var x= [];
console.log('x = empty array');
}
This checks if variable x exists and if it is, checks if it is a filled array. else it creates an empty array (or you can do other stuff);
If you are certain there is an array variable created there is a simple check:
var x = [];
if(!x.length){
console.log('empty');
} else {
console.log('full');
}
You can check my fiddle here with shows most possible ways to check array.
The following is my solution wrapped in a function that also throws
errors to manage a couple of problems with object scope and all types
of possible data types passed to the function.
Here's my fiddle used to examine this problem (source)
var jill = [0];
var jack;
//"Uncaught ReferenceError: jack is not defined"
//if (typeof jack === 'undefined' || jack === null) {
//if (jack) {
//if (jack in window) {
//if (window.hasOwnP=roperty('jack')){
//if (jack in window){
function isemptyArray (arraynamed){
//cam also check argument length
if (arguments.length === 0) {
throw "No argument supplied";
}
//console.log(arguments.length, "number of arguments found");
if (typeof arraynamed !== "undefined" && arraynamed !== null) {
//console.log("found arraynamed has a value");
if ((arraynamed instanceof Array) === true){
//console.log("I'm an array");
if (arraynamed.length === 0) {
//console.log ("I'm empty");
return true;
} else {
return false;
}//end length check
} else {
//bad type
throw "Argument is not an array";
} //end type check
} else {
//bad argument
throw "Argument is invalid, check initialization";;
}//end argument check
}
try {
console.log(isemptyArray(jill));
} catch (e) {
console.log ("error caught:",e);
}
the way I found to work (comming from another language) is to make a simple function to test.
create a function that check the size of the array and pass the lenght by parameter.
isEmpty(size){
if(size==0) {
return true;
} else {
return false;
}
}
//then check
if(isEmpty(yourArray.length)==true){
//its empty
} else {
//not empty
}
You should do this
if (!image_array) {
// image_array defined but not assigned automatically coerces to false
} else if (!(0 in image_array)) {
// empty array
// doSomething
}
For me sure some of the high rated answers "work" when I put them into jsfiddle, but when I have a dynamically generated amount of array list a lot of this code in the answers just doesn't work for ME.
This is what IS working for me.
var from = [];
if(typeof from[0] !== undefined) {
//...
}
Notice, NO quotes around undefined and I'm not bothering with the length.
Probably your image_array is not array but some OBJECT with length property (like string) - try
if(image_array instanceof Array && image_array.length)
function test(image_array) {
if(image_array instanceof Array && image_array.length) {
console.log(image_array,'- it is not empty array!')
} else {
console.log(image_array,'- it is empty array or not array at all!')
}
}
test({length:5});
test('undefined');
test([]);
test(["abc"]);
In my case, array_.length always returned 0, even if it had values inside. Probably, because of non-default indexes.
So to check if array is defined we use typeof _array !== 'undefined'
And then to check if it contains any date i just simply compare it to an empty array _array !== []
in ts
isArray(obj: any)
{
return Array.isArray(obj)
}
in html
(photos == undefined || !(isArray(photos) && photos.length > 0) )
When you create your image_array, it's empty, therefore your image_array.length is 0
As stated in the comment below, i edit my answer based on this question's answer) :
var image_array = []
inside the else brackets doesn't change anything to the image_array defined before in the code

Efficient way to compare arrays in javascript

I need to compare the elements from two arrays as follows:
arr1[0] ? arr2[0]
arr1[1] ? arr2[1]
arr1[2] ? arr2[2]
etc.
I wrote some code but it seems to be slow when I try to compare 1000 objects like this on each array :
{
"id":"event707",
"name":"Custom707",
"type":"disabled",
"default_metric":false,
"participation":"disabled",
"serialization":"always_record"
}
This is how my function looks like (just an example for two arrays with hard coded data).
function compare() {
var step = 0;
var fruits1 = [{"apple":25},{"bannana":36},{"orange":6}];
var fruits2 = [{"apple":25},{"bannana":36},{"orange":6}];
for(var i=0;i<fruits1.length;i++) {
for(var j=step;j<fruits2.length;j++) {
console.log("FRUIT1");
console.log(JSON.stringify(fruits1[i]));
console.log("FRUIT2");
console.log(JSON.stringify(fruits2[j]));
console.log("----------------------");
if(JSON.stringify(fruits1[i])!== JSON.stringify(fruits2[j])) {
//do something
}
step = step + 1;
break;
}
}
}
With an invention of Object.prototype.compare() and Array.prototype.compare() this job becomes a very simple task. Array compare can handle both primitive and reference type items. Objects are compared shallow. Let's see how it works;
Object.prototype.compare = function(o){
var ok = Object.keys(this);
return typeof o === "object" && ok.length === Object.keys(o).length ? ok.every(k => this[k] === o[k]) : false;
};
Array.prototype.compare = function(a){
return this.every((e,i) => typeof a[i] === "object" ? a[i].compare(e) : a[i] === e);
};
var fruits1 = [{"apple":25},{"bannana":36},{"orange":6}],
fruits2 = [{"apple":25},{"bannana":36},{"orange":6}];
console.log(fruits1.compare(fruits2));
Simple function without library:
var arr1 = [1,2,3];
var arr2 = [1,2,4];
//This function takes one item, the index of the item, and another array to compare the item with.
function compare(item, index, array2){
return array2[index] == item;
}
// the forEach method gives the item as first parameter
// the index as second parameter
// and the array as third parameter. All are optional.
arr1.forEach(function(item, index){
console.log(compare(item, index, arr2));
});
Combine this with the answer Abdennour TOUMI gave, and you have an object comparison method :)
For simple objects you could use JSON.stringify(obj1) === JSON.stringify(obj2).
More info on object comparison can be found in this answer
Use underscore array functions. I would go with intersection
http://underscorejs.org/#intersection
You can use the following static method for Object class : Object.equals
Object.equals=function(a,b){if(a===b)return!0;if(!(a instanceof Object&&b instanceof Object))return!1;if(a.valueOf()===b.valueOf())return!0;if(a.constructor!==b.constructor)return!1;for(var c in a)if(a.hasOwnProperty(c)){if(!b.hasOwnProperty(c))return!1;if(a[c]!==b[c]){if("object"!=typeof a[c])return!1;if(!Object.equals(a[c],b[c]))return!1}}for(c in b)if(b.hasOwnProperty(c)&&!a.hasOwnProperty(c))return!1;return!0};
console.log(
`"[1,2,3] == [1,2,3]" ?`,Object.equals([1,2,3],[1,2,3])
);
console.log(
`"[{"apple":25},{"bannana":36},{"orange":6}] == [{"apple":25},{"bannana":36},{"orange":6}]" ?`,Object.equals([{"apple":25},{"bannana":36},{"orange":6}], [{"apple":25},{"bannana":36},{"orange":6}])
);

Sort Array B after Array A, such that references and equal Primitives, maintain the exact Position

Update 2
I added a weight lookup to the sort function, which increased the performance by about 100% as well as the stability, as the previous sort function didn't consider all types, and as 1 == "1" the result depends on the initial order of the Array, as #Esailija points out.
The intent of the question is to improve this Answer of mine, I liked the question and since it got accepted and I felt like there is some performance to squeeze out of the sort function. I asked this question here since I hadn't many clues left where to start.
Maybe this makes things clearer as well
Update
I rephrased the complete question, as many people stated I was not specific enough, I did my best to specify what I mean. Also, I rewrote the sort function to better express the intent of the question.
Let arrayPrev be an Array (A) ,where A consists of 0 to n Elements' (E)
Let an Element either be
of a Primitive type
boolean, string, number, undefined, null
a Reference to an Object O, where O.type = [object Object] and O can consist of
0 to n Properties P, where P is defined like Element plus
an circular Reference to any P in O
Where any O can be contained 1 to n times. In the sense of GetReferencedName(E1) === GetReferencedName(E2)...
a Reference to an O, where O.type = [object Array] and O is defined like A
a circular Reference to any E in A
Let arrayCurr be an Array of the same length as arrayPrev
Illustrated in the following example
var x = {
a:"A Property",
x:"24th Property",
obj: {
a: "A Property"
},
prim : 1,
}
x.obj.circ = x;
var y = {
a:"A Property",
x:"24th Property",
obj: {
a: "A Property"
},
prim : 1,
}
y.obj.circ = y;
var z = {};
var a = [x,x,x,null,undefined,1,y,"2",x,z]
var b = [z,x,x,y,undefined,1,null,"2",x,x]
console.log (sort(a),sort(b,a))
The Question is, how can I efficiently sort an Array B, such that any Reference to an Object or value of a Primitive, shares the exact same Position as in a Previously, by the same compareFunction, sorted, Array A.
Like the above example
Where the resulting array shall fall under the rules.
Let arrayPrev contain the Elements' of a and arrayCurr contain the Elements' of b
Let arrayPrev be sorted by a CompareFunction C.
Let arrayCurr be sorted by the same C.
Let the result of sorting arrayCur be such, that when accessing an E in arrayCur at Position n, let n e.g be 5
if type of E is Object GetReferencedName(arrayCurr[n]) === GetReferencedName(arrayPrev[n])
if type of E is Primitive GetValue(arrayCurr[n]) === GetValue(arrayPrev[n])
i.e b[n] === a[n] e.g b[5] === a[5]
Meaning all Elements should be grouped by type, and in this sorted by value.
Where any call to a Function F in C shall be at least implemented before ES5, such that compatibility is given without the need of any shim.
My current approach is to Mark the Objects in arrayPrev to sort them accordingly in arrayCurr and later delete the Marker again. But that seems rather not that efficient.
Heres the current sort function used.
function sort3 (curr,prev) {
var weight = {
"[object Undefined]":6,
"[object Object]":5,
"[object Null]":4,
"[object String]":3,
"[object Number]":2,
"[object Boolean]":1
}
if (prev) { //mark the objects
for (var i = prev.length,j,t;i>0;i--) {
t = typeof (j = prev[i]);
if (j != null && t === "object") {
j._pos = i;
} else if (t !== "object" && t != "undefined" ) break;
}
}
curr.sort (sorter);
if (prev) {
for (var k = prev.length,l,t;k>0;k--) {
t = typeof (l = prev[k]);
if (t === "object" && l != null) {
delete l._pos;
} else if (t !== "object" && t != "undefined" ) break;
}
}
return curr;
function sorter (a,b) {
var tStr = Object.prototype.toString
var types = [tStr.call(a),tStr.call(b)]
var ret = [0,0];
if (types[0] === types[1] && types[0] === "[object Object]") {
if (prev) return a._pos - b._pos
else {
return a === b ? 0 : 1;
}
} else if (types [0] !== types [1]){
return weight[types[0]] - weight[types[1]]
}
return a>b?1:a<b?-1:0;
}
}
Heres a Fiddle as well as a JSPerf (feel free to add your snippet)
And the old Fiddle
If you know the arrays contain the same elements (with the same number of repetitions, possibly in a different order), then you can just copy the old array into the new one, like so:
function strangeSort(curr, prev) {
curr.length = 0; // delete the contents of curr
curr.push.apply(curr, prev); // append the contents of prev to curr
}
If you don't know the arrays contain the same elements, it doesn't make sense to do what you're asking.
Judging by the thing you linked, it's likely that you're trying to determine whether the arrays contain the same elements. In that case, the question you're asking isn't the question you mean to ask, and a sort-based approach may not be what you want at all. Instead, I recommend a count-based algorithm.
Compare the lengths of the arrays. If they're different, the arrays do not contain the same elements; return false. If the lengths are equal, continue.
Iterate through the first array and associate each element with a count of how many times you've seen it. Now that ES6 Maps exist, a Map is probably the best way to track the counts. If you don't use a Map, it may be necessary or convenient to maintain counts for items of different data types differently. (If you maintain counts for objects by giving them a new property, delete the new properties before you return.)
Iterate through the second array. For each element,
If no count is recorded for the element, return false.
If the count for the element is positive, decrease it by 1.
If the count for the element is 0, the element appears more times in the second array than in the first. Return false.
Return true.
If step 4 is reached, every item appears at least as many times in the first array as it does in the second. Otherwise, it would have been detected in step 3.1 or 3.3. If any item appeared more times in the first array than in the second, the first array would be bigger, and the algorithm would have returned in step 1. Thus, the arrays must contain the same elements with the same number of repetitions.
from the description, it appears you can simply use a sort function:
function sortOb(a,b){a=JSON.stringify(a);b=JSON.stringify(b); return a===b?0:(a>b?1:-1);}
var x = {a:1};
var y = {a:2};
var a = [1,x,2,3,y,4,x]
var b = [1,y,3,4,x,x,2]
a.sort(sortOb);
b.sort(sortOb);
console.log (a,b);
Your function always returns a copy of sort.el, but you can have that easier:
var sort = (function () {
var tmp;
function sorter(a, b) {
var types = [typeof a, typeof b];
if (types[0] === "object" && types[1] === "object") {
return tmp.indexOf(a) - tmp.indexOf(b); // sort by position in original
}
if (types[0] == "object") {
return 1;
}
if (types[1] == "object") {
return -1;
}
return a > b ? 1 : a < b ? -1 : 0;
}
return function (el) {
if (tmp) {
for (var i = 0; i < el.length; i++) {
el[i] = tmp[i]; // edit el in-place, same order as tmp
}
return el;
}
tmp = [].slice.call(el); // copy original
return tmp = el.sort(sorter); // cache result
};
})();
Note that I replaced sort.el by tmp and a closure. Fiddle: http://jsfiddle.net/VLSKK/
Edit: This (as well as your original solution)
only works when the arrays contain the same elements.
maintains the order of different objects in a
but
does not mess up when called more than twice
Try this
function ComplexSort (a, b)
{
if(typeof a == "object") {
a = a.a;
}
if(typeof b == "object") {
b = b.a;
}
return a-b;
}
var x = {a:1};
var y = {a:2};
var a = [1,x,2,3,y,4,x]
var b = [1,y,3,4,x,x,2]
a.sort(ComplexSort);
b.sort(ComplexSort);
console.log ("Consistent", a,b);

Categories