I have an javascript array and I want to delete an element based on the value of the array, this is my array and this is what I have tried without success.
array = []
array.push (["Mozilla","Firefox",1.10])
index = array.indexOf(["Mozilla","Firefox",1.10])
array.splice(index, 1)
But it doesn't work, any idea¿?
You're trying to compare arrays, which are objects and have unique addresses. Your index variable is -1.
Try ['Mozilla','Firefox',1.10] === ['Mozilla','Firefox',1.10] in your console, you'll see that just because two arrays have the same values, it doesn't mean they are the same array.
What you need is a deep-equals style of comparison, that checks each value in the array, to see if two arrays have a likeness.
Take a look at lodash's isEqual function for an idea.
Here's a simple looping function:
function deepIndex(array, comparison) {
var i, j;
main:
for (i = 0; i < array.length; i++) {
if (Array.isArray(array[i])) {
for (j = 0; j < array[i].length; j++) {
if (array[i][j] !== comparison[j]) {
continue main;
}
}
return i;
}
}
}
var arr = [];
arr.push('string', ['Mozilla','Firefox',1.10], 'thing');
var index = deepIndex(arr, ['Mozilla','Firefox',1.10])
console.log(index, arr);
arr.splice(index, 1);
console.log(arr);
Take a look at this:
// Array Remove - By John Resig (MIT Licensed)
Array.prototype.remove = function(from, to) {
var rest = this.slice((to || from) + 1 || this.length);
this.length = from < 0 ? this.length + from : from;
return this.push.apply(this, rest);
};
This is function, made by the Creator of JQUery.
Basically you take the Index of one thing and than it is getting removed
Array.prototype.remove = function(from, to) {
var rest = this.slice((to || from) + 1 || this.length);
this.length = from < 0 ? this.length + from : from;
return this.push.apply(this, rest);
};
//Equals Function taken from:
//http://stackoverflow.com/questions/7837456/comparing-two-arrays-in-javascript
Array.prototype.equals = function (array) {
// if the other array is a falsy value, return
if (!array)
return false;
// compare lengths - can save a lot of time
if (this.length != array.length)
return false;
for (var i = 0, l=this.length; i < l; i++) {
// Check if we have nested arrays
if (this[i] instanceof Array && array[i] instanceof Array) {
// recurse into the nested arrays
if (!this[i].equals(array[i]))
return false;
}
else if (this[i] != array[i]) {
// Warning - two different object instances will never be equal: {x:20} != {x:20}
return false;
}
}
return true;
}
array = [];
array.push (["Mozilla","Firefox",1.10]);
array.push (["Microsoft","Spartan",1.0]);
array.push (["Safari","Safari",1.4]);
index = indexOfArr(array,["Mozilla","Firefox",1.10]);
array.remove(index, index);
document.getElementById("length").innerHTML = array.length;
for(var i = 0; i < array.length; i++){
document.getElementById("elems").innerHTML += "<br>"+array[i];
}
function indexOfArr(hay, needle){
for(var i = 0; i < hay.length; i++){
if (hay[i].equals(needle)){
return i;
}
}
return -1;
}
<span id = "length"></span><br>
<span id = "elems">Elements:</span>
You can use the fiter metodh, instead of indexOf.
Within the callback of that method, you can choose different approaches:
Use toString on the arrays and compare the two strings
Test for the length and the content, by iterating over the contained elements
... Continue ...
In any case using === will solve the problem, unless the object contained is exactly the same against which you are trying to match.
By the same, I mean the same. We are non speaking about having the same content, but to be the same instance.
Loop over your array and check the equality:
array = [];
array.push(["Mozilla", "Firefox", 1.10]);
for (var i = 0; i < array.length; i++) {
if (arraysEqual(array[i], ["Mozilla", "Firefox", 1.10])) {
array.splice(i, 1);
}
}
function arraysEqual(a, b) {
if (a === b) return true;
if (a === null || b === null) return false;
if (a.length != b.length) return false;
for (var i = 0; i < a.length; ++i) {
if (a[i] !== b[i]) return false;
}
return true;
}
JSFiddle: http://jsfiddle.net/ghorg12110/r67jts35/
Based on this question : How to check if two arrays are equal with JavaScript?
You can do something like this
array = []
array.push (["Mozilla","Firefox",1.10])
tempArray = array[0];
index = tempArray.indexOf("Mozilla","Firefox",1.10)
array.splice(index, 1)
You can build on this if you put for loop instead of hard coding.
Related
As the title, if the input is [[1,2], [3,4], [1,3], [5,6], [6,5]], output should be [[1,2,3,4], [5,6]].
It's wrong on the recursive part. In my code, after running it, I will get [[1,2,3],[1,3,4],[5,6]], which means I need once more merge, but I'm confused how to continue the code until no sub-array contains common element.
Here is my code
function need_merge_or_not(arr)
{
for (var i = 0; i <= arr.length-1; i++) {
for (var j = i+1; j <= arr.length-1; j++) {
var arr_new = arr[i].concat(arr[j]);
//remove deplicates
var arr_merge = arr_new.filter(function (item, pos) {return arr_new.indexOf(item) == pos});
if (arr_merge.length < arr_new.length) {
return true;
}
}
}
return false;
}
function merge(arr)
{
if (arr.length >= 2) {
for (var i = 0; i <= arr.length-1; i++) {
for (var j = i+1; j <= arr.length-1; j++) {
var arr_new = arr[i].concat(arr[j]);
var arr_merge = arr_new.filter(function (item, pos) {return arr_new.indexOf(item) == pos});
if (arr_merge.length < arr_new.length) {
arr.splice(arr.indexOf(arr[i]), 1);
arr.splice(arr.indexOf(arr[j]),1);
arr.push(arr_merge);
}
}
if (need_merge_or_not(arr)) {
return merge(arr);
}
}
}
return arr;
}
I figured it out. Here is the code:
function merge(arr){
var input = [];
for(var i = 0; i < arr.length; i++){
input.push(arr[i]);
}
if (arr.length >= 2) {
for (var i = 0; i < arr.length; i++) {
for (var j = i+1; j < arr.length; j++) {
var arr_new = arr[i].concat(arr[j]);
//remove duplicates
var arr_merge = arr_new.filter(function (item, pos) {return arr_new.indexOf(item) == pos});
if (arr_merge.length < arr_new.length) {
arr.splice(arr.indexOf(arr[i]), 1, arr_merge);
arr.splice(arr.indexOf(arr[j]),1);
j--;
}
}
}
if (!arraysEqual(input, arr)) {merge(arr)};
}
return arr;
//Input:[[1,2], [3,4], [1,3], [5,6], [6,5]]
//Output:[[1,2,3,4], [5,6]]
}
function arraysEqual(a, b) {
if (a === b) return true;
if (a == null || b == null) return false;
if (a.length != b.length) return false;
for (var i = 0; i < a.length; ++i) {
if (a[i] !== b[i]) return false;
}
return true;
}
You could use two hash tables, one for the items and their groups and on for the result sets.
Basically the algorithm generates for the same group an object with a property and an array, because it allowes to keep the object reference while assigning a new array.
The main part is iterating the outer array and then the inner arrays and check inside, if it is the first item, then check the hash table for existence and if not exists, generate a new object with a values property and an empty array as value. Also assign the actual object to sets with item as key.
In a next step, the hash table is checked again and if not exist, then assign the object of the first element.
To maintain only unique values, a check is made and if the item does not exist, the item is pushed to the hash table's values array.
Then a part to join arrays follows by checking if the object of the first item is not equal to object of the actual item. If so, it delete from sets the key from the actual items's values first item and concat the array of the actual items to the first item's object's values. Then the values object is assigned to the actual item's object.
Later the sets are maped to the result set with iterating the sets object and the values property is taken as value.
var array = [[1, 2], [3, 4], [1, 3], [5, 6], [6, 5]],
groups = {},
sets = {},
result;
array.forEach(function (a) {
a.forEach(function (b, i, bb) {
if (i === 0 && !groups[b]) {
groups[b] = { values: [] };
sets[b] = groups[b];
}
if (!groups[b]) {
groups[b] = groups[bb[0]];
}
if (groups[b].values.indexOf(b) === -1) {
groups[b].values.push(b);
}
if (groups[bb[0]] !== groups[b]) {
delete sets[groups[b].values[0]];
groups[bb[0]].values = groups[bb[0]].values.concat(groups[b].values);
groups[b].values = groups[bb[0]].values;
}
});
});
result = Object.keys(sets).map(function (k) {
return sets[k].values;
});
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
In this Plunker example the following filter is used to make select box options selectable only once
http://plnkr.co/edit/BBqnTlxobUpiYxfhyJuj?p=preview
.filter('arrayDiff', function() {
return function(array, diff) {
console.log(diff);
var i, item,
newArray = [],
exception = Array.prototype.slice.call(arguments, 2);
for(i = 0; i < array.length; i++) {
item = array[i];
if(diff.indexOf(item) < 0 || exception.indexOf(item) >= 0) {
newArray.push(item);
}
}
return newArray;
};
});
I really need such a filter but the problem is that my diff variable isn't an array but a number (selected value). (It is 1,2,3 or undefined):
In this code diff is either 1,2,[3] or [].
How can I rewrite such a filter to work with a number instead of an array.
This is how I use the filter: http://plnkr.co/edit/L9hBa5LapAV76wHrwRnX?p=preview
Something like this:
.filter('arrayDiff', function() {
return function(array, diff) {
console.log(diff);
var i, item,
newArray = [],
exception = Array.prototype.slice.call(arguments, 2);
for(i = 0; i < array.length; i++) {
item = array[i];
if(diff == item || exception.indexOf(item) >= 0) {
newArray.push(item);
}
}
return newArray;
};
});
I have tried all filters, and methods available on stackoverflow. My original output was
Human,,,
Now after using this method
function removingEmptyString(array)
{
var item = "";
for( var i = 0; i < array.length; i++)
{
if(array[i] == "" || array[i] == null)
{
array.splice( i, 1 );
}
}
return array;
}
My output is
Human,
What in my code is wrong that I am still getting the last comma?
for (var index in output)
{
if (opt.options.showEmpty != true)
{
var check = arrayIsEmpty(output[index]);
if ( check == true )
{
continue;
}
else
{
var array = removingEmptyString(output[index]);
//console.log(index + "\t" + array);
//var array = arr(output[index]);
console.log(index+ "\t" + array);
//console.log(index+ "\t" + output[index]);
}
}
See your For loop doesn't work as you expected, You're looping through the array and when the condition matches, you're splicing the element on that index, but the for loop goes on incrementing, so only the next index is checked, but the splice method has reduced the array by one index so that, a "" element is now in the index that you already looped over.
What you need to do is to decrement the i value when the condition matches so that, the loop will once again iterate through the index. Hope that helps.
function removingEmptyString(array)
{
var item = "";
for( var i = 0; i < array.length; i++)
{
if(array[i] == "" || array[i] == null)
{
array.splice( i, 1 );
//decrement the index
i--;
}
}
return array;
}
Unless you really need to mutate the array, you should use the filter method. It's simpler than spliceing an index, and it's more clear what you're trying to do.
Try
array = array.filter(function (el) {
return typeof el === "string" && !!el && !/\s+/.test(el);
});
I am trying to loop over an array argument and return the first n elements of the passed array without using standard javascript functions such as slice, concat, push, pop etc...
var n = 0;
var anyArray = Array;
var SR = {};
SR.first = function(anyArray,n){
var isArray = (Object.prototype.toString.apply(anyArray) === '[object Array]');
var specification = (typeof n === "number");
if(isArray && specification){
for(i = 0; i < n; i++){
return Array(anyArray[i]);
}
}
else if (isArray || !specification){
return anyArray[0];
}
}
I do not want to build the return array "anyArray" by using +=. So, how would I proceed to have it return some thing like this [1,2,3,4] when "SR.first([1,2,3,4,5,6,7], 4);" is called?
var newArr = Array.apply(null, anyArray); // new Array using original content
newArr.length = n; // truncate the length of the new Array
return newArr; // return it
One small edge case will be when anyArray has only one member, which is a number. You'll need to guard against that scenario.
I don't understand why you would not want to use Array operations like push and slice, but this would work:
if ( isArray && specification ) {
var result = [];
for ( var i = 0; i < n; i++ ) {
result[i] = anyArray[i];
}
return result;
}
else ...
If for some reason you really don't want to use native javascript functions, you can assign each element to your return array one by one.
var returnArray = [];
if(isArray && specification) {
for(i = 0; i < n; i++) {
returnArray[i] = anyArray[i];
}
}
return returnArray;
SR.first = function(anyArray,n){
var newArray = [];
for(i = 0; i < n; i++){
newArray[newArray.length] = anyArray[i];
}
return newArray;
}
First of all - global variable it's really bad practice! You don't need declare anyArray and n, becouse its a function arguments, and its declared on function call.
Second problem - that you can put number of elements bigger than array length - you must check this situation.
var SR = {};
SR.first = function(anyArray,n){
var isArray = (anyArray instanceof Array),
specification = (typeof n === 'number'),
tmp = new Array;
console.log(isArray, specification);
if(isArray && specification){
for(i = 0, l = anyArray.length; i < n && i < l; i++){
tmp[i] = anyArray[i];
}
return tmp;
} else if (isArray || !specification){
return anyArray[0];
}
}
There's plenty examples available on how to sort an javascript array based on it's numeric values. What would however be appropriate way to fetch all elements from myArray with the property prop1 with it's according value value1?
Here's my array:
var myArray = [
{
"id":"2",
"name":"My name",
"properties":{"prop1":"value1"}
}];
Thanks
You can just access it by dot or bracket notation and push the matching members to your new/filtered array, for example:
var newArray = [];
for(var i=0, l = myArray.length; i<l; i++) {
if(myArray[i].properties.prop1 == "value1") newArray.push(myArray[i]);
}
Your question is a bit ambiguous though, if you're trying to get the {"prop1":"value1"} object, not the parent, then just change newArray.push(myArray[i]) to newArray.push(myArray[i].properties).
Provide a compare function to sort by arbitrary properties:
function compareMyObjects(a, b) {
var valA = a.properties.prop1.value1;
var valB = b.properties.prop1.value1;
if(valA > valB) return 1;
if(valA < valB) return -1;
return 0;
}
myArray.sort(compareMyObjects);
https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/sort
Go through each element in your array. For each element, check each property to see if it matches the one you're looking for.
function filterArray(array, property, value) {
var newArray = [];
for (var i = 0; i < array.length; i++) {
for (var j in array[i].properties) {
if (j === property && array[i].properties.hasOwnProperty(j)) {
if (array[i].properties[j] == value) {
newArray.push(array[i]);
}
}
}
}
}
var newarray=myarray.filter(function(itm){
return itm.properties.prop1==='value1';
});
Filter, like the array methods indexOf and map, may be worth providing for browsers that don't have it- this version is from Mozilla Developer Site-
if(!Array.prototype.filter){
Array.prototype.filter= function(fun, scope){
var L= this.length, A= [], i= 0, val;
if(typeof fun== 'function'){
while(i< L){
if(i in this){
val= this[i];
if(fun.call(scope, val, i, this)){
A[A.length]= val;
}
}
++i;
}
}
return A;
}
}