I have an array of objects in javascript. I use jquery.
How do i get the first element in the array? I cant use the array index - as I assign each elements index when I am adding the objects to the array. So the indexes arent 0, 1, 2 etc.
Just need to get the first element of the array?
If you don't use sequentially numbered elements, you'll have to loop through until you hit the first one:
var firstIndex = 0;
while (firstIndex < myarray.length && myarray[firstIndex] === undefined) {
firstIndex++;
}
if (firstIndex < myarray.length) {
var firstElement = myarray[firstIndex];
} else {
// no elements.
}
or some equivalently silly construction. This gets you the first item's index, which you might or might not care about it.
If this is something you need to do often, you should keep a lookaside reference to the current first valid index, so this becomes an O(1) operation instead of O(n) every time. If you're frequently needing to iterate through a truly sparse array, consider another data structure, like keeping an object alongside it that back-maps ordinal results to indexes, or something that fits your data.
The filter method works with sparse arrays.
var first = array.filter(x => true)[0];
Have you considered:
function getFirstIndex(array){
var result;
if(array instanceof Array){
for(var i in array){
result = i;
break;
}
} else {
return null;
}
return result;
}
?
And as a way to get the last element in the array:
function getLastIndex(array){
var result;
if(array instanceof Array){
result = array.push("");
array.pop;
}
} else {
return null;
}
return result;
}
Neither of these uses jquery.
Object.keys(array)[0] returns the index (in String form) of the first element in the sparse array.
var array = [];
array[2] = true;
array[5] = undefined;
var keys = Object.keys(array); // => ["2", "5"]
var first = Number(keys[0]); // => 2
var last = Number(keys[keys.length - 1]); // => 5
I was also facing a similar problem and was surprised that no one has considered the following:
var testArray = [];
testArray [1245]= 31;
testArray[2045] = 45;
for(index in testArray){
console.log(index+','+testArray[index])
}
The above will produce
1245,31
2045,45
If needed you could exist after the first iteration if all that was required but generally we need to know where in the array to begin.
This is a proposal with ES5 method with Array#some.
The code gets the first nonsparse element and the index. The iteration stops immediately with returning true in the callback:
var a = [, , 22, 33],
value,
index;
a.some(function (v, i) {
value = v;
index = i;
return true;
});
console.log(index, value);
If you find yourself needing to do manipulation of arrays a lot, you might be interested in the Underscore library. It provides utility methods for manipulating arrays, for example compact:
var yourArray = [];
yourArray[10] = "foo";
var firstValue = _.compact(yourArray)[0];
However, it does sound like you are doing something strange when you are constructing your array. Perhaps Array.push would help you out?
Related
I work on an Angular project and I built an array.
Now I'd like to rename one of the items of the array. I found the way to rename the keys of an array but I still don't know how to do to apply this to its values.
Here is my array below.
I'd like to change 'valueC' by 'valueZ'.
myArray = ['valueA', 'valueB', 'valueC']
I tried the following code :
for (const k in this.myArray) {
if (k == "valueC") {
this.myArray[k] = "valueZ";
}
But it does not work.
Could you help me ?
Any help would be very appreciated, thanks.
Below are two possible methods!
const myArray = ['valueA', 'valueB', 'valueC']
//rename - if index known
myArray[2] = 'valueZ';
console.log('if index known', myArray);
//rename - if index not known
const foundIndex = myArray.findIndex(x => x === 'valueC');
if (foundIndex > -1) {
myArray[2] = 'valueZ';
}
console.log('if index not known', myArray);
Your code just needs a minor correction:
if (this.myArray[k] == "valueC")
Try this:
const myArray = ['valueA', 'valueB', 'valueC'];
for (const k in myArray) {
if (myArray[k] == "valueC") {
myArray[k] = "valueZ";
}
}
console.log(myArray);
You need to track the index, easy with a forEach
this.myArray.forEach((k, index) => {
if (k == "valueC") {
this.myArray[index] = "valueZ";
}
})
My prefered way :
Though, be sure to have the value "valueC" inside the array
otherwise indexOf will return a -1, provoquing an error
// without index control
this.myArray[this.myArray.indexOf("valueC")] = "valueZ";
// with index control
const index = this.myArray.indexOf("valueC")
if (index >= 0) {
this.myArray[index] = "valueZ";
}
Also note this for future usage :)
for (const k in array) : in that case k is the index of elements in array
for (const k of array) : in that case k is the value of elements in array
On top of all the other solutions here, another approach, and one I believe is better in that it gets you in the mindset of immutability, is to return a new object instead of modifying the current one.
Ex:
this.myArray = this.myArray.map(x => {
if(x !== 'valueC')
return x;
return 'valueZ';
});
So map here will return a new array object for us, in this case a string array given your current array is a string array. Another pattern in use here is only checking for the negative case. Instead of having if/else or a chain of them, we know that for all case that aren't 'valueC' we retain their original value and only valueC's value needs to change to valueZ
I have created below function to delete a custom element from an array:
Array.prototype.removeElement=function(x){
var index = this.indexOf(x);
if (index !== -1) {
this.splice(index, 1);
}
};
It works fine with below array:
var data = [1,2,3,4];
data.removeElement(2); //returns [1,3,4]
But when I have more than one item from a certain element it removes only first occurrence.
var data = [1,2,3,4,2];
data.removeElement(2);
// returns [1,3,4,2] while I expect to get [1,3,4]
I know I can do this by using loops, But I am curious to know if there is any cleaner code?
Using JS .filter() array method can be handy. Try this code,
// Create a function in array prototype as
Array.prototype.removeElement = function(x){
return this.filter((elem)=>elem!==x);
}
This should work a charm, but I don't think. There is any other way to do this other than looping.
2 solutions: one returns a new array and the other does it in-place
Solution 1: returns a new array
You can leverage the built-in filter method
function removeAllOccurences (array, element) {
return array.filter((ele) => ele !== element);
}
console.log(removeAllOccurences([1,2,3,4,3],3)); // [1,2,4]
Solution 2: in-place using recursion
function removeAllOccurences (array, element) {
if (!array.includes(element)) {
return array;
} else {
let index = array.indexOf(element);
array.splice(index, 1);
return removeAllOccurences(array, element);
}
}
console.log(removeAllOccurences([1,2,3,4,3],3)); // [1,2,4]
Try a while loop to continue using the splice method until that element is no longer present.
Array.prototype.removeElement=function(x){
var index = this.indexOf(x);
if (index !== -1) {
while (this.includes(x)) {
index = this.indexOf(x);
this.splice(index, 1);
}
}
}
The while loop uses the array.includes method to determine whether the array still contains that element's value, and if it does, it updates the index to the next element x, after which it will then splice the element like your code did. The while loop breaks when array.includesis false in turn, removing all the elements equal to x from the array.
I would like to scan through a JS array and determine if all the elements are unique, or whether the array contains duplicates.
example :
my_array1 = [1, 2, 3]
my_array2 = [1, 1, 1]
I want get result like this :
my_array1 must be return true, because this array element is unique
and array2 must be return false, because this array element is not unique
How can I go about writing this method?
Sort your array first of all, and then go for a simple comparison loop.
function checkIfArrayIsUnique(arr) {
var myArray = arr.sort();
for (var i = 0; i < myArray.length; i++) {
if (myArray.indexOf(myArray[i]) !== myArray.lastIndexOf(myArray[i])) {
return false;
}
}
return true;
}
if you want to check for uniqueness you can also do this.As stated on the comment i do not assert this is as the only best option.There are some great answers down below.
var arr = [2,3,4,6,7,8,9];
var uniq = []; // we will use this to store the unique numbers found
// in the process for doing the comparison
var result = arr.slice(0).every(function(item, index, array){
if(uniq.indexOf(item) > -1){
// short circuit the loop
array.length=0; //(B)
return false;
}else{
uniq.push(item);
return true;
}
});
result --> true
arr.slice(0) creates a temporary copy of the array, on which the actual processing is done.This is because when the uniqueness criteria is met i clear the array (B) to short circuit the loop.This will make sure the processing stops as soon as the criteria is met.
And will be more nicer if we expose this as a method on a Array instance.
so we can do something like this [1,2,3,5,7].isUnique();
Add the following snippet and you are ready to go
Array.prototype.isUnique = function() {
var uniq = [];
var result = this.slice(0).every(function(item, index, arr) {
if (uniq.indexOf(item) > -1) {
arr.length = 0;
return false;
} else {
uniq.push(item);
return true;
}
});
return result;
};
arr.isUnique() --> true
DEMO
You may try like this:
function uniqueArray(arr) {
var hash = {}, result = [];
for ( var i = 0, l = arr.length; i < l; ++i ) {
if ( !hash.hasOwnProperty(arr[i]) ) {
hash[ arr[i] ] = true;
result.push(arr[i]);
}
}
return result;
}
try this :-
var my_array1 = [1, 2, 3]
var my_array2 = [1, 1, 1]
function isUnique(obj)
{
var unique=obj.filter(function(itm,i,a){
return i==a.indexOf(itm);
});
return unique.length == obj.length;
}
alert(isUnique(my_array1))
alert(isUnique(my_array2))
Demo
I think you can try with Underscore js , a powerful javascript library
Example the way to use underscore
function checkUniqueArr(arr){
var unique_arr = _.uniq(arr);
return arr.length == unique_arr.length;
}
The most efficient way to test uniqueness is:
function isUnique(arr) {
for(var i = 0; i < arr.length; i++) {
if (arr.indexOf(arr[i]) != i) return false;
}
return true;
}
This is O(n2) at worst case. At most time, it doesn't need to finish scanning for not-unique array.
function containsDuplicates(arr) {
var seen = {};
var duplicate = false;
for (var i = 0; i < arr.length; i++) {
if (seen[arr[i]]) {
duplicate = true;
break;
}
seen[arr[i]] = true;
}
return duplicate;
}
jsFiddle
Best-case: O(1) time and space - second element is the duplicate
Average/worst-case: O(n) time and space - no duplicates, or the duplicate is in the middle
Many of the answers here seem to be relying on some complex interspersion of array methods, which are inherently iterative, and generally don't seem appropriate for this fairly simple task. Algorithmically, this problem can be solved in O(n) time, but any nesting of indexOf/filter/map (or similar array methods) in a for loop means that your computation time will grow (at best) quadratically with your array size, rather than linearly. This is inefficient in time.
Now, in general, micro-optimization really is not necessary unless you have identified this to be a performance bottleneck in your application. But this kind of algorithm, in my opinion, is something you design (in pseudocode) and match to your application's needs before you even start coding. If you will have a huge data-set in your array, you will probably appreciate not having to look through it several times to get your answer. Of course, the caveat here is that you're trading time complexity for space complexity, since my solution requires O(n) space for caching previously seen values.
If you need to check all element are unique then following will do the trick
<script>
my_array1 = [11, 20, 3]
my_array2 = [11, 11, 11]
var sorted1= my_array1.sort();
var sorted2= my_array2.sort();
if(sorted1[0]==sorted1[sorted1.length-1])
alert('all same');
if(sorted2[0]==sorted2[sorted2.length-1])
alert('all same');
</script>
I just came up with this answer.
I'm preparing for an interview.
I think this is rock solid.
let r = [1,9,2,3,8];
let r2 = [9,3,6,3,8];
let isThereDuplicates= r.slice().sort().some((item,index,ar)=>(item ===ar[index+1]));
console.log('r is: ',isThereDuplicates) // -> false. All numbers are unique
isThereDuplicates= r2.slice().sort().some((item,index,ar)=>(item ===ar[index+1]));
console.log('r2 is: ',isThereDuplicates) //->true. 3 is duplicated
I first slice and sort without mutating the original array.
r.slice().sort()
Then I check that for at least one item, item is equal to the next item on the array.
.some((item,index,array)=>
item === array[index+1]
);
I found a solution to where I get returned an array of elements without duplicates:
Array1 = Array1.filter(function(val) {
return Array2.indexOf(val) == -1;
});
However, I want to modify this code just a little bit. Instead of being returned an array without duplicates, I want to do something when there is a duplicate. The problem is, I'm not sure how exactly this code works. The thing is I'm not sure how val gets set, or what it even is.
for (var i = 0; i < json.length; i++) {
var item = json[i];
// if json.indexOf(val?), do something
}
Read the docs for the Array filter method then. The val parameter of the callback will be passed the single array items, i.e. json[i] or item in your case:
for (var i = 0; i < json.length; i++) {
var item = json[i];
if (json.indexOf(item) >= 0) {
// do something
}
}
var newArray = array1.filter(function(v, i) {
return array1.indexOf(v) == i;
});
This will return only unique itesm from array1;
array1.filter(function(v, i) {
// write your code here ('v' is individual value and 'i' is its index)
// don't return any anything if you don't want unique array to be returned.
// 'array1.indexOf(v) == i' checks if current value is duplicate from previous any values.
// try putting console.log on values you don't understand like (console.log(v,i) for values of 'v' and 'i')
return array1.indexOf(v) == i;
});
and off-curse you can loop an array with for loop as
for(i in array1){
// where i is index of array1, to get current value use array1[i]
if(array2.indexOf(array1[i]) >= 0){
// do something
}
console.log(i);
}
val is set by Array.prototype.filter, which calls the callback function on each element in the array. Since you don't want to filter you can use Array.prototype.forEach instead, which also calls the callback function once for each element in the array:
Array1.forEach(
// This function is called once per element in Array1
function(val){
if(Array2.indexOf(val) != -1){ // Check if that element is also in Array2
// `val` is in both arrays,
// Do something with it
}
}
);
You can utilize some modern libraries... like underscorejs.
Intersection is what you're looking for i guess: http://underscorejs.org/#intersection
_.intersection([1, 2, 3], [101, 2, 1, 10], [2, 1]);
=> [1, 2]
So your code may be something like
if(_.insersection(arr1, arr2)){
//since [] array is Falsy in JS this will work as a charm
}
From MDN: indexOf
Returns the first index at which a given element can be found in the array, or -1 if it is not present.
From MDN: filter
Creates a new array with all elements that pass the test implemented by the provided function.
The first function works by returning true when an item from array1 isn't found in array2 (== -1). i.e.: Iterate through A and add anything not found in B.
So, to change to return only duplicates return true for anything that is found in both:
Array1 = Array1.filter(function(val) {
return Array2.indexOf(val) >= 0;
});
Array1 now contains only items with duplicates.
Code:
var testarray = [];
var test1 = "ashutosh";
var test2 = "ashutosh2";
if (test1 != test2) {
testarray.push = "ashutosh3";
testarray.push = "ashutosh4";
alert(testarray.length);
}
if (testarray.length != 1) {
alert(testarray.length);
alert(testarray[testarray.length - 1]);
alert(testarray[testarray.length - 2]);
}
But when all the alerts are showing up undefined. I have no clue why is this happening.
push is a function, not a property, so instead of
testarray.push="ashutosh3";
it's
testarray.push("ashutosh3");
Here's how I'd update that code, FWIW, but I think the only substantive change is doing the push correctly and using >= 2 rather than != 1 in the length check at the end (since otherwise if the array is empty you're looking at entries -1 and -2, which will be undefined):
var testarray = [];
var test1 = "ashutosh";
var test2 = "ashutosh2";
if (test1 !== test2) {
testarray.push("ashutosh3");
testarray.push("ashutosh4");
alert(testarray.length);
}
if(testarray.length >= 2) {
alert(testarray.length);
alert(testarray[testarray.length-1]);
alert(testarray[testarray.length-2]);
}
T.J. Crowder already answer the issue with push but I'm guessing you are new to JavaScript so here are some useful tips I wished knew earlier.
For Each Loops
Instead of writing a standard for loop, you can use a forEach loop.
for( i in testArray ){
console.log( i );
}
Objects
Till hashtables and modules make their appearance to JS, we are left with using arrays. Here is the easiest method I know of to make an object.
var ArrayUtils = {
"print" : function(array) {
console.log(array);
}
}
Since ArrayUtils is an list, you can extend it using either dot or bracket notation
ArrayUtils["size"] = function(array){
return array.length;
}
ArrayUtils.indexOf = function(array, i){
return array[i];
}
Higher-Order Functions
Arrays in JavaScript come with a built-in map, reduce and filter functions. These three functions are highly useful when it comes to writing elegant code.
Map, passes each element in an sequence into a function
testArray.map( function(i){ console.log(i); } );
Reduce, well reduces the array into a single value. In this example i'm calculating the sum of the array
testArray.reduce( function(x,y) { return x+y; } );
Filter, as you could guess removes elements from an array. In JS, .filter() returns a new array
testArray = testArray.filter( function(i) { return ( i > 0 ); } );
I also read that JS has iterator and generator support. They are powerful iteration tools and worth checking out if you are going to heavily use iteration in your code base. I don't so, it's been something I put off as a todo.