Getting index of matching element - javascript

I have an array of elements in Javascript
var axes = [{id: "a"}, {id: "b"}]
and I have one of these items in a variable
var axis = {id: "b"}
I wanted a one liner in JavaScript (similar to the Linq one liners I can do in C#) where I will get the index of the array in which this element exists. So, in this example I will get the answer 1.
How is this possible?

You can use array prototype map method:
var axisIndex = axes.map(function(x) {return x.id; }).indexOf(axis.id);
https://stackoverflow.com/a/16100446/1414562
And to support older browsers, you could use the jQuery's way:
var axisIndex = $.inArray(axis.id, $.map(axes, function(x){return x.id}));

It looks like you want to create a new axis object that looks the same as one of the elements in the axes array, but isn't actually an element of the axes array. If this is the case, the indexOf method won't work because it would expect to find the exact object you're searching for in the array.
There are ways of doing this - it would usually involve more than one line though (the one line restriction seems fairly trivial). However, I've found a solution, despite it looking rather ugly, and better suited to a code golfing problem than real live code.
axes.indexOf(axes.filter(function(el) {if (el.id === axis.id) return true; }).shift());

Related

Sorting a dynamically filled array of objects

I have an array that is initialized like such var generationObject = [{string:"", score: 0}];
which I then fill dynamically:
for(var i = 0; i < amount_offspring; i++)
{
// "load" text into array and send the string to see if it evolves
generationObject[i].string = evolve(start_text, characters, mutation_rate);
// then score the string
generationObject[i].score = score(target_text, generationObject.string);
}
I then want to sort this array by score. I don't know what's best, to sort it in the for loop or sort the entire array afterwards.
I will then take the string of the highest scoring object and pass it through the function again, recursively.
So what would be a good way to go about this sort function? I've seen some here use this
generationObject.sort(function(a, b) {
return (a.score) - (b.score);
});
But I'm not sure if .sort is still supported? This didnt seem to work for me though.
generationObject is an array, not an object, so score(target_text, generationObject.string); could be the problem, as .string will be undefined. (Did you mean generationObject[i].string?)
Try building your array like this:
var generationObject = []
for(var i = 0; i < amount_offspring; i++)
{
evolved_string = evolve(start_text, characters, mutation_rate)
generationObject.push({
string: evolved_string,
score: score(target_text, evolved_string)
})
}
And then Array.prototype.sort should do the trick.
You should write your sorting logic outside the for loop, since if you put it inside, the object array will be sorted N times, where N being the iterations of your loop. The following are two ways to do it-
By using sort() function- To clarify your question, sort() is still supported across almost all the browsers. If you are still concerned about the browser compatibility, you can check the MDN documentation to see the list of supported browsers.
generationObject = generationObject.sort(function(a, b) {
return parseInt(a.score) - parseInt(b.score);
});
By using underscorejs-
In underscore, you can take advantage of the sortBy() function.
Returns a (stably) sorted copy of list, ranked in ascending order by the results of running each value through iteratee. iteratee may also be the string name of the property to sort by (eg. length).
You can simply do this in underscorejs-
generationObject = _.sortBy(generationObj, 'score');

remove specific item from a json object

i am trying to remove some items in an json object list, the ones that have a specific group. My JSON looks like this.
var events = [
{"id":"19","name":"sports","group":"1"},
{"id":"20","name":"school","group":"2"},
{"id":"21","name":"fun","group":"1"}
]
I tried this
for(var i in events)
if(events[i].group == deleted_group)
events.splice(i, 1);
But the problem of this, is that if i have to remove more items, it bugs out. Is there another easy way to to this ? I am open for sugestion even using underscore.js .
Thank you in advance, Daniel!
Try this
var events = [
{"id":"19","name":"sports","group":"1"},
{"id":"20","name":"school","group":"2"},
{"id":"21","name":"fun","group":"1"}
]
console.log(_.reject(events, function(event){ return event.group == '1'; }));
When you're using the "splice" function to remove elements from the array inside a for loop,
you need to shift your current index back when removing an item since the array is reindexed.
Also take a look at the array functions like "filter" for a more convenient way, read more on MDN.
You can use delete operator to delete objects (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/delete):
delete events[0]
The problem with delete is, that in your array, as a value of events[0] it will leave undefined.
So another way (the way I would choose for your simple example) is to just rewrite the array:
var temp_events = [];
for(var i in events)
if(events[i].group != deleted_group)
temp_events[temp_events.length] = events[i];
events = temp_events;
Executing splice in a for loop has complexity n^2 (where n is number of elements). Rewriting has linear complexity.

How to build a Javascript Array Delta

I have an array of arrays where the position of the value is important in that this data is used to ultimately layout a grid.
[[a,b,c,d],[a,b,c,d][a,b,c,d],[a,b,c,d]] // Original data
Based on an action, values within this "dataset" can change, but the size will never change.
[[a,b,c,d],[a,b,b,b][a,c,c,c],[a,b,c,d]] // Modified data
What I'd like to do is to return a dataset that only contains the delta values:
[[null,null,null,null,],[null,null,b,b],[null,c,null,c],[null,null,null,null,]]
Now, I do always know the max X and Y of the dataset, and could simply loop through the original dataset, comparing it's value to the corresponding value and build a new array, but it seems like there could be a more efficient way to accomplish this.
That said, my js-fu is minimal at best, and that's why I'm brining the problem here. Are there any language provided methods for accomplishing this? Suggested approaches? etc?
A bit of array mapping should do the trick.
Here's a fiddle: http://jsfiddle.net/C8jnr/
Given the following:
var arr_A = [[a,b,c,d],[a,b,c,d],[a,b,c,d],[a,b,c,d]];
var arr_B = [[a,b,c,d],[a,b,b,b],[a,c,c,c],[a,b,c,d]];
function deltaArrays(arr1, arr2)
{
return arr1.map(function(el_arr,i,arr){
return el_arr.map(function(el, j){
return (el == arr2[i][j]) ? null : arr2[i][j];
});
});
}
Calling deltaArrays on the two will yield the expected delta array;
deltaArrays(arr_A, arr_B) = [[null,null,null,null,],[null,null,b,b],[null,c,null,c],[null,null,null,null,]]
I don't believe there is a built in way to do this. Your best bet is to loop through each of the array elements and compare them with the new array, adding it to a list/dictionary if it is different.

return a range of values from an array in underscore.js

I have an array with the following data
var a = [1,2,3,4,5,6,7]
I am looking for a method in underscore.js or backbone.js in which I can return the elements with a specified range. for ex:
filter(2,5) should return [3,4,5,6]
which is the 2nd to 5th index elements in the array. Any pointers for me ?
Javascript Array should be defined like below,
var a = [1,2,3,4,5,6,7]; //not inside {}
And then you can use array native slice method to get elements from a specific position
a.slice(2, 6) //should return 3,4,5,6
Edit:
I very well know that the functionality is available in JScript. I was asking if its available in backbone or underscore. You are asking like why would you want an ice cube instead of water because ice will turn to water eventually.
Underscore js do not have function like slice as it is already available in native js.
Step 1:
Switch to Lodash. (https://lodash.com/)
Note: dangerous step, you will never go back.
Step 2:
Use the _.slice function like this:
_.slice(a, 2, 5)

What's the best way to dynamically add or remove objects from container in JavaScript?

For example, I have an array of strings, ['12', '34', '56'], and I want to dynamically update this array by adding additional elements ('78', '90'), or by removing some elements ('34', '56').
Not sure if there's a better data structure/library that gets the job done. Can someone shed some lights for a JS newbie?
In JavaScript, you can usually do anything with the provided arrays and objects.
To add elements, use Array.prototype.push.
var array = ["12", "34", "56"];
array.push("78", "90");
To properly remove elements without leaving holes, you need to find their index (you can use Array.prototype.indexOf in good browsers, there is a shim on the page for IE) and use Array.prototype.splice.
array.splice(array.indexOf("34"), 1);
array.splice(array.indexOf("56"), 1);
Note that if you already know the index and the count, you can just do
array.splice(1, 2); //Removes 2 elements starting at index 1
Also note that splice can also add elements with the same call. Just put them as the last parameters. That means you could do this:
var array = ["12", "34", "56"];
array.splice(1, 2, "78", "90"); //array is now ["12", "78", "90"]
Everyone here seems to be suggesting array based solutions but if all you are ever going to do is add/remove elements and check if they are present or not you can consider using an object as a hash table.
var elems = {
'a': true,
'b':true
};
//add someone to the list
elems['c'] = true;
//check if someone is in the list
elems.hasOwnProperty('c');
//remove someone from the list
delete elems[c];
To add to an array use .push.
var arr = ['12', '34', '56'];
arr.push('78', '90');
Removing a specific element, may take a bit more work. To to that, you'll need to copy the array into a new one (without the element(s) you want to remove).
John Resig (creator of jQuery) posted a function to remove array elements by their indexes (which you'll need to get 1st). His function is here.
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);
};
var arr = ['12', '34', '56'];
arr.remove(arr.indexOf('34'));
arr.remove(arr.indexOf('56'));
Update: .splice could also work to remove elements.
var arr = ['12', '34', '56'];
arr.splice(arr.indexOf('34'), 1);
arr.splice(arr.indexOf('56'), 1);
Note: Array.indexOf may not work in all browsers. There is a function that will add it to older browsers at the MDN docs page.
Adding is easy, just use the push() method to add an element to the end of the array.
You can remove the first / last item with shift() and pop() respectively, but if you want to remove a specific element you need to find that element's index using indexOf(), then remove it using splice().
See https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/ for more about the methods.
After learning how this can be done using basic ECMAScript array manipulation (as addressed by the other answers),
I would recommend a set of higher-order functions. Mainly map, flatmap, and filter.
These are rolled into one in the jQuery.map function. However, similar constructs can be found elsewhere, such as in the ECMAScript 5th Edition Array functions (unfortunately does not have a flatmap), or additional libraries like Functional JavaScript, or manually created (which is a great learning exercise).
Happy coding.

Categories