Javascript: Filtering twodimensional array - javascript

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;
}
}

Related

Remove object from array if it is contained in another array

I am trying to remove an object from an array, if that object's property (unique) is included in the other array. I know I can do a nested for-loop like this:
for(i = 0; i < array.length; i++) {
for(j = 0; j < array2.length; j++) {
if(array[i].Email === array2[j].Email) {
//remove array[i] object from the array
}
}
}
Or whatever. Something like that. Is there an ES6 filter for that? I can easily do a filter up against a regular array with strings, but doing it with an array of objects is a bit more tricky.
If you are fine using ES6, you can even look into array.find, array.filter or array.some
Array.findIndex
var result = array.filter(x=>{
return array2.findindex(t=> t.Email === x.Email) === -1
})
Array.some
var result = array.filter(x=>{
return !array2.some(t=> t.Email === x.Email)
})
Not very optimal, but try this
array = array.filter( function( item ){
return array2.filter( function( item2 ){
return item.Email == item2.Email;
}).length == 0;
});
Try with find as well, it won't iterate all the elements and will break after first match itself
array = array.filter( function( item ){
return array2.find( function( item2 ){
return item.Email == item2.Email;
}) == undefined;
});
You could use a Set with ES6
var array = [/* your data */],
array2 = [/* your data */],
set = new Set(...array2.map(a => a.Email));
array = array.filter(a => !set.has(a.Email));
Try this one.... :)
if(array[i].Email === array2[j].Email){
// splice(Index you want to remove,to witch element)
array1.splice(i,1);
}
splice() can remove element of your array. You need to pass witch element. witch element is the start of delete. How many elements should delete. That's 1.. :)
How about writing a function, passing the parameters and simply collecting the output?
function arrNotInArrKey(arr1, arr2, key) {
for (var i = 0; i < arr1.length; i++) {
for (var j = 0; j < arr2.length; j++) {
if (arr1[i][key] === arr2[j][key]) {
arr1.splice(i, 1);
i--;
}
}
}
return arr1;
}
console.log(
arrNotInArrKey([{
name: 1
}, {
name: 3
}, {
name: 2
}], [{
name: 2
}], "name")
);
You can use shift function. here it's example.
http://www.w3schools.com/js/tryit.asp?filename=tryjs_array_shift
for(i = 0; i < array.length; i++) {
for(j = 0; j < array2.length; j++) {
if(array[i].Email === array2[j].Email) {
array.shift(array[i].Email);
}
}
}

Javascript Looping through objects

var a = {
element:'input',
parent:'div1',
name:'inp',
type:'text',
value:'aa'
}
I want to loop through this object starting from name attribute using for in loop
But I am unable to do this using for in loop
is there any way to loop through the object starting from the name attribute
Old way:
for (var key in a) {
if (a.hasOwnProperty(key)) {
// todo something with a[key]
}
}
ES6 way:
Object.keys(a).forEach(function(key) {
// todo something with a[key]
});
for(var prop in a) {
console.log(a[prop]);
}
You could do something like this:
var keys = Object.keys(a);
var length = keys.length;
var startAt = keys.indexOf("name");
for(var i = 0; i < length ; i++) {
var prop = keys[(i+startAt)%length];
console.log(prop, a[prop]);
}
Or:
var keys = Object.keys(a).sort(function(a,b){ return a !== "name" });
for(var i = 0; i < keys.length; i++) {
var prop = keys[i];
console.log(prop, a[prop]);
}
Or:
var keys = Object.keys(a);
var idx = keys.indexOf("name");
if(idx > 0) {
var tmp = keys[0];
keys[0] = keys[idx];
keys[idx] = tmp;
}
for(var i = 0; i < keys.length; i++) {
var prop = keys[i];
console.log(prop, a[prop]);
}
But keep in mind that objects are unordered lists even though most browsers keep object properties in the order in which they were added.
I believe you can do it as follows:
function loopFromIndex(input, index) {
var started = false;
for (var property in input) {
started = started || (index === property);
if (started) {
//process iteration
}
}
}
You are still looping the whole property set, but when you encounter the given index, you will start the real loop.

Javascript delete array element from array by value

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.

javascript: Prevent representing added Array's attributes as elements (in Chrome)

I am using this snippet to extend Array's functionality with getUnique function:
Array.prototype.getUnique = function() {
var u = {}, a = [];
for (var i = 0, l = this.length; i < l; ++i) {
if (u.hasOwnProperty(this[i])) {
continue;
}
a.push(this[i]);
u[this[i]] = 1;
}
return a;
};
The slight drawback is that the attribute getUnique is printed together with array elements if I console.log an array:
["126", "125", getUnique: function]
It is slightly disturbing even if I know that getUnique is not considered as an array element. This happens in Chrome. Not in Firefox as far as I know. Is there a way to prevent it?
Use Object.defineProperty and enumerable:
Object.defineProperty(Array.prototype, 'getUnique',
{ enumerable: false
, configurable: true
, writable: true
, value: function ()
{ var u = {};
var a = [];
for (var i = 0, l = this.length; i < l; ++i)
{ if (u.hasOwnProperty(this[i])) continue;
a.push(this[i]);
u[this[i]] = 1;
}
return a;
}
});
By default, a property is enumerable (even if it's not a direct property of an instance), which means that it is visible through any for-in loop (or Object.keys) of the array. Chrome does something similar to a for-in loop on an array, which is why it is represented as it is.
Note that this function only works in (relatively) modernish browsers which support ES5, which means that IE < 9, some older Android browsers and other mobile devices may not be able to use this code. This is one of the reasons why some people recommend against extending the prototypes of native constructors, as this issue can break code that isn't well constructed against these issues. What people who believe this usually recommend is to not place the function on the prototype:
function getUnique(arr)
{ var u = {};
var a = [];
for (var i = 0, l = array.length; i < l; ++i)
{ if (u.hasOwnProperty(arr[i])) continue;
a.push(arr[i]);
u[arr[i]] = 1;
}
return a;
}
I'd also like to point out that only one object will be ever printed by the getUnique function, as it is technically incorrect in its implementation. While rather similar, objects are not dictionaries and can only have string keys, which means that any object (no matter the contents) will have a string value of '[object Object]', which means that when your function encounters another object (even if it has different values), it will not be added to the returned array. While inefficient, the only way I can think of is to iterate through the array each time:
function getUnique(arg)
{ 'use strict';
var O = Object(arg);
var len = O.length >>> 0;
var A = [];
var indexOf = function (arg, searchElement)
{ for (var i = 0, l = arg.length; i < l; ++i) if (arg[i] === searchElement) return i;
return -1;
};
for (var k = 0; k < len; ++k)
{ var elementK = O[k];
var kPresent = k in O;
if (!kPresent || indexOf(A, elementK) !== -1) continue;
A[A.length - 1] = elementK;
}
return array;
}

How can I iterate over all unique pairs of entries in an object?

I currently have an array data structure that I iterate over like this, calling foo on each unique pair of elements.
for(var i = 0; i < arr.length; i++) {
for(var j = i + 1; j < arr.length; j++) {
foo(arr[i], arr[j]);
}
}
However, I've realized that I'd rather use an object instead of an array, since I can then add and remove elements by name very easily.
However, I can't see an obvious way to iterate over such an object. The closest I can get is:
for(i in obj) {
for(j in obj) {
foo(obj[i], obj[j]);
}
}
Obviously, this will do each pair twice, and even produce a pair of identical elements. Is there an easy way to iterate over an object in the same way as I do in the array in my first code sample?
Update:
Performance testing the solutions on jsperf.
My solution that was at first written as a comment:
Add an if (i < j) condition in the inner loop. It might not be the best solution, but it would work as long as the foo function does the same thing for foo(2, 10) and foo(10, 2):
for(i in obj) {
for(j in obj) {
if (i < j) {
foo(obj[i], obj[j]);
}
}
}
Assuming I understand your question... maybe check to see if the value has already been visited by the outer loop?
var visited = {}
for(i in obj) {
visited[i] = true;
for(j in obj) {
if(j in visited){ continue; }
foo(obj[i], obj[j]);
}
}
Use Object.keys() to get the list of keys out as an array:
keys = Object.keys();
for(i=0;i<keys.length;i++) {
for(j=i+1;j<keys.length;j++) {
foo(obj[keys[i]], obj[keys[j]]);
}
}
Maybe You can try unset used objects:
for(i in obj) {
var a = obj[i];
delete obj[i];
for(j in obj) {
foo(a, obj[j]);
}
}
http://jsfiddle.net/bXcvb/
If you need to original obj in tact see: How do I correctly clone a JavaScript object?
You can push the object keys into an array:
var obj_keys = [];
for (i in obj) {
obj_keys.push(i);
}
for(i = 0; i < obj_keys.length; ++i) {
for(j = i + 1; j < obj_keys.length; ++j) {
foo(obj[obj_keys[i]], obj[obj_keys[j]]);
}
}

Categories

Resources