The title may a little confusing. But i think it is clear:
var a = ["A1", "B13", "C123"];
I want to ignore first value in elements and get rest of them. So my new array should look like this:
var b = ["1", "13", "123"];
Use .map() to create a new Array of modified values of the original.
var b = a.map(function(item) {
return item.slice(1);
});
This iterates the original Array, passes each item in the Array as the first argument to the function, and sets the return value of the function as the values for the new Array.
For IE8 and lower, you'll need to implement a patch. One is available from MDN.
Using .map, you can return a new array which is generated by passing every element in the existing array through a function:
var b = a.map(function(v) {
return v.substr(1);
});
Note that .map is an ES5 function that doesn't exist on older browsers. A shim is available at the above link.
var b = [];
for (var i = 0; i < a.length; ++i)
{
b[i] = a[i].substring(1);
}
Live Demo
The forEach way
var a = ["A1", "B13", "C123"],
b = [];
a.forEach(function (element) {
b.push(element.slice(1));
});
console.log(b);
on jsfiddle
The map way
var b = a.map(function (element) {
return element.slice(1);
});
The for way
var l = a.length;
var b = [];
for (var i = 0; i < l; i += 1) {
b.push(a[i].slice(1));
}
Ultimate speed is still the for loop (except for maybe grand daddy)
So as I ended up including all of the above, it didn't feel right to leave the grand daddy of them all out of the equation.
The while way
var b = [];
var i = 0;
var l = a.length;
while (i < l) {
b.push(a[i].slice(1));
i += 1;
}
I also include a RegExp and jquery version for a bit of a giggle.
(lodash also has it's own map function)
You can see the jsperf
Related
I am trying to build an array that should look like this :
[
[{"name":"Mercury","index":0}],
[{"name":"Mercury","index":1},{"name":"Venus","index":1}],
[{"name":"Mercury","index":2},{"name":"Venus","index":2},{"name":"Earth","index":2}],
...
]
Each element is the concatenation of the previous and a new object, and all the indexes get updated to the latest value (e.g. Mercury's index is 0, then 1, etc.).
I have tried to build this array using the following code :
var b = [];
var buffer = [];
var names = ["Mercury","Venus","Earth"]
for (k=0;k<3;k++){
// This array is necessary because with real data there are multiple elements for each k
var a = [{"name":names[k],"index":0}];
buffer = buffer.concat(a);
// This is where the index of all the elements currently in the
// buffer (should) get(s) updated to the current k
for (n=0;n<buffer.length;n++){
buffer[n].index = k;
}
// Add the buffer to the final array
b.push(buffer);
}
console.log(b);
The final array (b) printed out to the console has the right number of objects in each element, but all the indexes everywhere are equal to the last value of k (2).
I don't understand why this is happening, and don't know how to fix it.
This is happening because every object in the inner array is actually the exact same object as the one stored in the previous outer array's entries - you're only storing references to the object, not copies. When you update the index in the object you're updating it everywhere.
To resolve this, you need to create new objects in each inner iteration, or use an object copying function such as ES6's Object.assign, jQuery's $.extend or Underscore's _.clone.
Here's a version that uses the first approach, and also uses two nested .map calls to produce both the inner (variable length) arrays and the outer array:
var names = ["Mercury","Venus","Earth"];
var b = names.map(function(_, index, a) {
return a.slice(0, index + 1).map(function(name) {
return {name: name, index: index};
});
});
or in ES6:
var names = ["Mercury","Venus","Earth"];
var b = names.map((_, index, a) => a.slice(0, index + 1).map(name => ({name, index})));
Try this:
var names = ["Mercury","Venus","Earth"];
var result = [];
for (var i=0; i<names.length; i++){
var _temp = [];
for(var j=0; j<=i; j++){
_temp.push({
name: names[j],
index:i
});
}
result.push(_temp);
}
console.log(result)
try this simple script:
var b = [];
var names = ["Mercury","Venus","Earth"];
for(var pos = 0; pos < names.length; pos++) {
var current = [];
for(var x = 0; x < pos+1; x++) {
current.push({"name": names[x], "index": pos});
}
b.push(current);
}
Having the set {a,b,c} I want find all the subsets in recursive manner. I have already solved this problem using bitmasking but I want to understand the way that a person stated in this youtube video here
There are other stackoverflow threads about this problem but I have not found any that are solving the way she states in the video, she says,
"take the subsets of a and b, clone them and then add c to all the clones"
I am having trouble picturing the "simple" recursive method that would accomplish this. Is the recursive method, once exhausted, have all the subsets of A,B and the clones of A,B (duplicates at this point) and then propagates back up adding C to only the clones?
In other words, I start with a for loop on the set, I call my recursive function, I then do a for loop of n-1 and call my recursive method in that for loop, I cannot see how I can get C to be added to already existing subset clones in an array that is being built with recursion.
function SubsetBuilder(set) {
this.set = set;
}
SubsetBuilder.prototype.getSubsetsRecursive = function () {
//Set = {a,b,c}
//take the subsets of a and b, clone them and then add c to all the clones
//subsets of {a,b}=
//{}
//{a}
//{b}
//{a,b}
var n = this.set.length;
var result = [];
var recurseForSubsets = function (prefix, index) {
for (var i = index; i < n -1; i ++) {
result.push(prefix + this.set[i]);
recurseForSubsets(prefix + this.set[i], i + 1);
}
}
for (var j = 0; j < n; j++) {
recurseForSubsets("", j);
}
return result;
}
SubsetBuilder.prototype.printSubsets = function () {
var self = this;
if (!self.set)
return;
var n = this.set.length;
for (var i = 0; i < (1 << n) ; i++) {
var subset = [];
for (var j = 0; j < n; j++) {
if (((i >> j) & 1) === 1) { // bit j is on
subset.push(this.set[j]);
}
}
console.log(subset);
}
}
var set = ['a', 'b', 'c'];
var obj = new SubsetBuilder(set);
//obj.printSubsets();
console.log(obj.getSubsetsRecursive());
I gave this a try and came up with
function getSubsets(inp) {
if (inp.length == 1) {
// return the single item set plus the empty set
return [inp, []];
} else {
var e = inp.pop();
var s = getSubsets(inp);
// duplicate the elements of s into s1 without creating references.
// this might not be the best technique
var s1 = s.concat(JSON.parse(JSON.stringify(s)));
// add e to the second group of duplicates
for (var i=s.length; i < s1.length; i++) {
s1[i].push(e);
}
return s1;
}
}
var set = ['a', 'b', 'c'];
var list = getSubsets(set);
console.log(list);
// result
// [["a"], [], ["a", "b"], ["b"], ["a", "c"], ["c"], ["a", "b", "c"], ["b", "c"]]
The lady in the video said that all subsets of {a,b,c} can be formed from taking all the subsets of {a,b} and appending c to each one. Not entirely accurate (a valid subset of {a,b,c} does not have to include c), but a starting place for the algorithm. I changed the rule to all subsets of {a,b,c} can be formed from taking two copies of the subsets of {a,b} and appending c to each element of the second copy.
I think I could get rid of or simplify the if, because essentially the second block of code does the same as the first, so it's not ideal.
To me it makes sense that the algorithm runs in O(2^n) because the results vary in the same way (3 elements in the input array = 2^3 elements in the output array) - you might have to forgive my use of JSON to assume that complexity though. I'd find a better way to deep clone the array, even so, that might add more complexity.
MyIds has just two Id numbers 1 and 2
var MyIds = [1,2]
but MyObject has three Id numbers 1, 2 and 3 (In reality this has about 500 Id's)
var MyObject = [{id:1,size:21,length:31},{id:2,size:22,length:32},{id:3,size:23,length:33}]
and I want to make a new variable that looks like this, I need some magic code that will compare the two variables and only return the details of the objects where the Is's match
var Result = [{id:1,size:21,length:31},{id:2,size:22,length:32}]
I'm happy to use jQuery if it help
Use Array.prototype.filter()
var Result = MyObject.filter(function(item){
return MyIds.indexOf(item.id) >-1;
});
It can be easily solved with underscore or lodash with something like:
Result = _.filter(MyObject, function (item) {
return _.indexOf(item.id, MyIds) !== -1;
});
I admit, this is a lazy answer. There is probably a way to make it without adding a news library. But lodash is so cool :)
It can be done without jQuery:
var MyIds = [1,2];
var MyObject = [{id:1,size:21,length:31},{id:2,size:22,length:32},{id:3,size:23,length:33}];
var Result = [];
MyObject.forEach(function(element) {
MyIds.forEach(function(id){
if(element.id == id)
Result.push(element);
});
});
A more diverse sollution without using any library:
function find(propName, filters, collection){
var temp = [];
for(var i = 0; i < collection.length; i++){
for(var j = 0; j < filters.length; j++){
if(collection[i][propName] === filters[j]){
temp.push(collection[i]);
break;
}
}
}
return temp;
Apologies if this is a duplicate, but I can't seem to find the solution.
I am trying to find a specific string pattern in an array.
I want to find all values in data that contain 'underscore r underscore'. I then want to create a new array that contains only those keys and values.
var data = ["something", "bar_r_something"];
var resultArray = new Array();
for (var i = 0; i < data.length; i++) {
var bar = /_r_/;
if ($.inArray(bar, data[i].length) > 0)
{
console.log("found _r_");
resultArray.push(data[i]);
}
};
I just can't seem to get that $.inArray to work, it seems to always kick out -1.
var data = ["something", "bar_r_something"];
var resultArray = new Array();
for (var i = 0; i < data.length; i++) {
var bar = /_r_/;
if (bar.test(data[i])) {
alert("found _r_");
resultArray.push(data[i]);
}
};
console.log(resultArray);
Here you go, it doesn't use $.inArray, but Regex instead, hope that's cool!
EDIT
If you wanted to go a bit more fancy, you can use JavaScript's filter method like so:
var data = ["something", "bar_r_something"];
var resultArray = data.filter(function(d){
return /_r_/.test(d);
});
console.log(resultArray);
I think what you are looking for is $.grep(). Also $.inArray() does not test the values against a regex, it tests for equality.
var regex = /_r_/
var resultArray = $.grep(data, function(item){
return regex.test(item)
})
Demo: Fiddle
suppose I do..
var arr = Array();
var i = 3333;
arr[i] = "something";
if you do a stringify of this array it will return a string with a whole bunch of undefined numeric entries for those entries whose index is less than 3333...
is there a way to make javascript not do this?
I know that I can use an object {} but I would rather not since I want to do array operations such as shift() etc which are not available for objects
If you create an array per the OP, it only has one member with a property name of "333" and a length of 334 because length is always set to be at least one greater than the highest index. e.g.
var a = new Array(1000);
has a length of 1000 and no members,
var a = [];
var a[999] = 'foo';
has a length of 1000 and one member with a property name of "999".
The speedy way to only get defined members is to use for..in:
function myStringifyArray(a) {
var s = [];
var re = /^\d+$/;
for (var p in a) {
if (a.hasOwnProperty(p) && re.test(p)) {
s.push(a[p]);
}
}
return '' + s;
}
Note that the members may be returned out of order. If that is an issue, you can use a for loop instead, but it will be slower for very sparse arrays:
function myStringifyArray(a) {
var s = [];
var re = /^\d+$/;
for (var i=0, iLen=a.length; i<iLen; i++) {
if (a.hasOwnProperty(i)) {
s.push(a[i]);
}
}
return '' + s;
}
In some older browsers, iterating over the array actually created the missing members, but I don't think that's in issue in modern browsers.
Please test the above thoroughly.
The literal representation of an array has to have all the items of the array, otherwise the 3334th item would not end up at index 3333.
You can replace all undefined values in the array with something else that you want to use as empty items:
for (var i = 0; i < arr.length; i++) {
if (typeof arr[i] == 'undefined') arr[i] = '';
}
Another alternative would be to build your own stringify method, that would create assignments instead of an array literal. I.e. instead of a format like this:
[0,undefined,undefined,undefined,4,undefined,6,7,undefined,9]
your method would create something like:
(function(){
var result = [];
result[0] = 0;
result[4] = 4;
result[6] = 6;
result[7] = 7;
result[9] = 9;
return result;
}())
However, a format like that is of course not compatible with JSON, if that is what you need.