I have an array that contains any number of subarrays, each containing exactly two values.
i.e: interestArray[[1, 5], [3, 8] ... ]
How do I remove say the subarray containing the values [3, 8]?
My code is:
$('td', container).click(function(){
if(!$(this).hasClass('purchased') && !$(this).hasClass('manu'))
{
var manuId = $(this).parent().children('td:first-child').data('manu-id');
var typeId = $(this).data('type-id');
if($(this).hasClass('interest'))
{
$(this).removeClass('interest');
$(this).parent().children('td.manu').removeClass('interest');
var index = interestArray.indexOf([manuId, typeId]);
interestArray.splice(index, 1);
} else {
$(this).addClass('interest');
$(this).parent().children('td.manu').addClass('interest');
interestArray.push([manuId, typeId]);
}
//updateSurvey(interestsArray);
console.log(interestArray)
}
})
The below section does not work, and simply removes the first subarray.
var index = interestArray.indexOf([manuId, typeId]);
interestArray.splice(index, 1);
Here's a generic approach with your requirements:
var arr = [[1,2],[3,4],[5,6]];
var remove = [3,4];
for (var i=0; i<arr.length; i++) {
if (arr[i][0] == remove[0] && arr[i][1] == remove[1]) {
arr.splice(i, 1);
break;
}
}
console.log(arr); //=> [[1,2],[5,6]]
For a general approach, you can filter the array:
var reducedArray = interestArray.filter(function (item) {
return item[0] != manuId || item[1] != typeId;
});
You cannot use indexOf because that looks for the identical object (not merely an equivalent one).
If you're running an earlier version of JS that doesn't have Array.filter, there's a nice shim on the filter doc page linked to above.
Here is my personal solution more complete to avoid multiple entry issue and the break; thing seen above, it also avoids an issue if the array is after entry removal (it is jquery based but you can make a regular loop if you feel more comfy with it):
$.each( answers, function( index, value ){
if (typeof answers[index] != "undefined")
{
if(answers[index]["question_id"]==answer_to_del)
{
delete answers[index];
}
}
});
//Clean answer array from empty values created above
answers = answers.filter(function(n){ return n != undefined });
Related
This is a very simple question but I am not been able to wrap my head around it.
I have an array of pages with n number of page names, I want to run a loop with some page names not included in it.
var arr = ["page-name", "page-name-two", 'page-3', 'some-more', 'another-page'];
for (var page in arr) {
if (arr[page] !== "page-name" || arr[page] !== "some-more") {
console.log(arr[page])
}
}
Now the result that I want is this:
page-name-two
page-3
another-page
What am I doing wrong?
Just take logical AND && instead of logical OR ||.
Please use a for loop with a variable for the index instead of the keys of an object.
Source:
Why is using “for…in” with array iteration a bad idea?
var arr = ["page-name", "page-name-two", 'page-3', 'some-more', 'another-page'];
for (var i = 0; i < arr.length; i++) {
if (arr[i] !== "page-name" && arr[i] !== "some-more") {
console.log(arr[i]);
}
}
The expression
arr[i] !== "page-name" || arr[i] !== "some-more"
is always true, because for exampe if
arr[i] === "page-name"
then the other part is true, because of
"page-name" !== "some-more"`.
You should use .filter() to filter values from first array and then perform whatever action you want to perform on resultant array. This will save your from writing a lot of OR / AND conditions in case you need to filter more values.
let arr1 = ["page-name", "page-name-two", 'page-3', 'some-more', 'another-page'],
arr2 = ["page-name", 'some-more'];
let result = arr1.filter(s => !arr2.includes(s));
console.log(result);
I would store the values that you're looking to eliminate, then run Array.filter on your list of all page names to find matches. If a name matches, remove it from the final array.
// This can be a array of whatever strings you're looking to eliminate from the array
const valuesToFilter = ['page-name', 'some-more'];
// Your original array
const arr = ["page-name", "page-name-two", 'page-3', 'some-more', 'another-page'];
// Use Array.filter to eliminate anything that doesn't pass the filter test
const filteredArr = arr.filter(page => {
let foundMatch = false;
valuesToFilter.forEach(value => {
if (page === value) {
foundMatch = true;
}
})
if (!foundMatch) return page;
});
console.log(filteredArr);
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.
I am using a set of numerical values in an array where certain values are be repeated. I want to find the indices of ALL of the occurrences of a repeated value.
For example, I have the following code using indexOf():
var dataset = [2,2,4,2,6,4,7,8];
return dataset.indexOf(2);
But this only gives the index of the first occurrence of 2. (i.e. it returns the value 0.)
However, I want the indices for ALL the occurrences of 2 to be returned (i.e. 0,1,3). How can I do this? (I know I could use a for loop, but I'm wondering if there's a better way to do this having without iterating through the whole array. Basically, I'm trying to save the overhead of explicitly iterating through the whole array.)
#Bagavatu: If you don't want a for loop you could try this fiddle -
var dataset = [2,2,4,2,6,4,7,8];
var results = [];
var ind
// the while loop stops when there are no more found
while( ( ind = dataset.indexOf( 2 ) ) != -1 ){
results.push( ind + results.length )
dataset.splice( ind, 1 )
}
return results;
NOTE: using a for loop would be MUCH quicker. See comments.
var dataset = [2,2,4,2,6,4,7,8];
var results = [];
for ( i=0; i < dataset.length; i++ ){
if ( dataset[i] == 2 ){
results.push( i );
}
}
return results;
You can use the filter() method of the Array object to handle nicely:
var dataset = [2, 2, 4, 2, 6, 4, 7, 8];
var indexs = [];
dataset.filter(function(elem, index, array){
if(elem == 2) {
indexs.push(index);
}
});
alert(indexs);
And here is some more documentation on the filter() method, as well as a fallback for older browsers.
Here you have an example: Try if yourself
var dataset = [2,2,4,2,6,4,7,8];
// We get the first indexOf number 2
var prev = dataset.indexOf(2);
// While we find indexes we keep searching
while (prev != -1) {
alert(prev);
// we get the indexOf number 2 starting in the previous position + 1
prev = dataset.indexOf(2, prev + 1);
}
Looks like this functionality may not be possible out-of-the-box, but there is a 'plugin' available here by creating a Array.prototype.allIndexOf function.
It still iterates over the entire list (which is required), but it abstracts the logic a little bit.
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?