I want to make object with different key 'number' with values from arr;
var arr = [1,2,4],
q = {},
a = { number : null };
for (i=0;i<3;i++) {
q[i] = a;
q[i].number = arr[i];
}
But with this i got 3 same objects.
I tried to make a closure like
var arr = [1,2,4],
q = {},
a = { number : null };
for (i=0;i<3;i++) {
(function(number) {
q[number] = a;
q[number].number = arr[number];
})(i)
}
but result is the same. What i am doing wrong?
You already define object a. And when you write a to q[i] it just write pointer to this object. Fixed code:
var arr = [1,2,4],
q = {};
for (i = 0; i < 3; i++) {
q[i] = {};
q[i].number = arr[i];
}
And if cleans up here:
var array = [1, 2, 4],
q = Object.create(null);
array.forEach(function(value, index) {
$.extend(q[index], {
number: value
});
});
.forEach()
Related
I am writing a function called "countStr".
I need to return an object where each key is a word in the given string, with its value being how many times that word appeared in the given string. If the string is empty it must return an empty object.
Here's my function so far:
function countStr(str) {
myObject = {};
if(str.length === 0) {
return myObject;
} else {
myArray = str.split(' ');
for(var i = 0; i < myArray; i++) {
var key = myArray[i];
if(myObject.hasOwnProperty(key)) {
myObject[key]++;
} else {
myObject[key];
}
}
return myObject;
}
}
var output = countStr('ask me lots get me lots');
console.log(output); // --> IT MUST OUTPUT {ask: 1, me: 2, lots: 2, get: 1}
Can you tell me how to fix it?
There are small issues with your code.
You need to iterate from zero to the length of the array.
You need to initialize the object items with 1 in the else case.
You should use local variables with the var to avoid polluting your top level namespace.
Here is the fixed version:
function countStr(str) {
var myObject = {};
if(str.length === 0) {
return myObject;
} else {
var myArray = str.split(' ');
for(var i = 0; i < myArray.length; i++) {
var key = myArray[i];
if(myObject.hasOwnProperty(key)) {
myObject[key]++;
} else {
myObject[key] = 1;
}
}
return myObject;
}
}
var output = countStr('ask me lots get me lots');
console.log(output);
You can use Array#reduce() like this
function countStr(str) {
return str.trim().length ? str.split(' ').reduce((o,s)=>{
o[s] = o[s] || 0;
o[s]++;
return o;
}, {}) : {};
}
var output = countStr('ask me lots get me lots');
console.log(output); // --> {ask: 1, me: 2, lots: 2, get: 1}
Other wise in your code, you were missing Array.length in your for condition and the else should be like myObject[key]=1
function countStr(str) {
myObject = {};
var myArray = [];
if(str.length === 0) {
return myObject;
} else {
myArray = str.split(' ');
for(var i = 0; i < myArray.length; i++) {
var key = myArray[i];
if(myObject.hasOwnProperty(key)) {
myObject[key]++;
} else {
myObject[key]=1;
}
}
return myObject;
}
}
var output = countStr('ask me lots get me lots');
console.log(output);
Okay, say I have a $scope.object = {}; and in this object I have various variables like such;
$scope.object.a = 0;
$scope.object.b = 0;
$scope.object.c = 0;
$scope.object.d = 0;
so the display would be object = { a : 0, b : 0, c : 0, d : 0 }
Now I have a set of code that sets certain values from 0 to 1 based on some checkboxes. So say what I have now is
$scope.object.a = 1;
$scope.object.b = 1;
$scope.object.c = 1;
$scope.object.d = 0;
Here's the tricky part for me, how do i get my $scope.object to fetch all the variables with a value of 1 only?
Sorry if the question is not too clear, but I'm trying my best to explain it, cheers! :D
You can iterate on the object to get the keys which match your value.
function getAllKeys(object, value) {
keys = [];
for(i in object) {
if(object[i] === value) keys.push(i);
}
return keys;
}
// ....
$scope.object.a = 1;
$scope.object.b = 1;
$scope.object.c = 1;
$scope.object.d = 0;
getAllKeys($scope.object, 1); // ["a", "b", "c"]
a little example :
$scope.object = {};
$scope.object.a = 1;
$scope.object.b = 1;
$scope.object.c = 1;
$scope.object.d = 0;
// if you want an object with only element equal to 1
var resObj = {};
// if you want an array of element name equal to 1 in object
var resArray = [];
for(var i in $scope.object){
if($scope.object[i]==1){
resObj[i]=1;
resArray.push(i);
}
}
console.log(resObj);
console.log(resArray);
You can try something like this
var obj = {a:1,a:1,a:1,a:0};
for(var i in obj){
if(obj[i]==0){
delete obj[i];
}
}
console.log(obj); //gives the desired output
Following code will do the magic,
var yourArray= [];
Object.keys($scope.object).forEach(function(key){
if($scope.object[key]===1){
yourArray.push(key);
}
})
I have a JavaScript array with 8 elements and some elements are repeating. I want to create separate arrays for identical elements.
example:
original array is [1,1,1,3,3,1,2,2]
resulting arrays will be [1,1,1,1],[3,3],[2,2]
I want a function similar to this:
var array=[1,1,1,3,3,1,2,2];
var createNewArrays=function(array){
for (var i = 0; i < array.length; i++) {
for (var j = 0; j < array.length; j++) {
}
}
};
You could use a hash table as reference to the sub arrays for the collection.
var array = [1, 1, 1, 3, 3, 1, 2, 2],
result = [];
array.forEach(function (a) {
a in this || result.push(this[a] = []);
this[a].push(a);
}, Object.create(null));
console.log(result);
var arr = [1,1,1,3,3,1,2,2];
var hash = Object.create(null);
var result = arr.reduce(function(r, n) {
if(!hash[n]) {
hash[n] = [];
r.push(hash[n]);
}
hash[n].push(n);
return r;
}, []);
console.log(result);
And an ES6 solution that uses Map, and spread:
const arr = [1,1,1,3,3,1,2,2];
const result = [...arr.reduce((r, n) =>
r.set(n, (r.get(n) || []).concat(n)),
new Map()).values()];
console.log(result);
Let's assume you want the resulting arrays to be properties on an object keyed by the value they represent. You just loop through the array, creating or adding to the arrays on the object properties as you go:
var array=[1,1,1,3,3,1,2,2];
var result = {};
array.forEach(function(entry) {
(result[entry] = result[entry] || []).push(entry);
});
console.log(result);
That's a bit dense, here's a clearer version:
var array=[1,1,1,3,3,1,2,2];
var result = {};
array.forEach(function(entry) {
var subarray = result[entry];
if (!subarray) {
subarray = result[entry] = [];
}
subarray.push(entry);
});
console.log(result);
For example I have
var nums = [1,2,3,4,5,6,7,8,9];
Is there a way to write this:
var multiplesOf2 = nums.filter(...)
var multiplesOf3 = nums.filter(...)
var greaterThan7 = nums.filter(...)
And have it be as efficient as
var multiplesOf2 = [], multiplesOf3 = [], greaterThan7 = [];
nums.forEach(function (num) {
if (...) { multiplesOf2.push(num); }
if (...) { multiplesOf3.push(num); }
if (...) { greatherThan7.push(num); }
})
?
Here's one way to do it:
var LazyArray = defclass({
constructor: function (xs) {
this.xs = xs;
this.fs = [];
},
iterate: function () {
var xs = this.xs, m = xs.length;
var fs = this.fs, n = fs.length;
for (var i = 0; i < m; i++) {
var x = xs[i];
for (var j = 0; j < n; j++) {
var f = fs[j], p = f(x, i, xs);
if (p) fs.splice(j--, 1), n--; // break out of the loop
}
}
fs.length = 0;
},
filter: function (f) {
var ys = [];
this.fs.push(function (x) {
if (f(x)) ys.push(x);
});
return ys;
}
});
Here's how you would use it:
var nums = new LazyArray([1,2,3,4,5,6,7,8,9]);
var multiplesOf2 = nums.filter(...);
var multiplesOf3 = nums.filter(...);
var greaterThan7 = nums.filter(...);
nums.iterate();
Note however that performance-wise there's no real benefit. If the input array has m items and there are n calls to filter then:
Traditionally you would loop through m items n times.
In this case you're looping through n iterators m times.
In either case the time complexity is O(m * n). There's no real benefit of lazy evaluation unless you get to skip a few computations which you would otherwise unnecessarily have to do using strict evaluation.
P.S. You can extend the LazyArray class with functions for map, reduce, etc. just as easily.
Edit: I forgot the definition of defclass:
function defclass(prototype) {
var constructor = prototype.constructor;
constructor.prototype = prototype;
return constructor;
}
That's all folks.
I can only guess that you want the .forEach() to be a little cleaner. You can use .reduce() if you think it helps.
var res = nums.reduce(function (obj, num) {
if (...) { obj[2].push(num); }
if (...) { obj[3].push(num); }
if (...) { obj[7].push(num); }
return obj;
}, {2:[],3:[],7:[]});
In ECMAScript 6, you'll be able to assign results to individual variables using destructuring assignment.
let {2:two, 3:three, 7:seven} = nums.reduce(function (obj, num) {
if (...) { obj[2].push(num); }
if (...) { obj[3].push(num); }
if (...) { obj[7].push(num); }
return obj;
}, {2:[],3:[],7:[]});
You'd need to test the performance, but perhaps something like this will work if you want to pass in functions
function filters(list /* test, test, test*/) {
var i, j, arr = [], tests;
tests = Array.prototype.slice.call(arguments, 1);
j = tests.length;
for (i = 0; i < j; ++i) arr[i] = [];
list.forEach(function (element, index, array) {
var i;
for (i = 0; i < j; ++i)
if (tests[i](element, index, array))
arr[i].push(element);
});
return arr;
}
filters(
[1, 2, 3, 4, 5, 6, 7, 8, 9], // first arg the Array
function (e) {return 0 === e % 2;}, // any number of tests to filter
function (e) {return 0 === e % 3;},
function (e) {return e > 7;}
);
/*
[
[2, 4, 6, 8],
[3, 6, 9],
[8, 9]
]
*/
I have two arrays like below
var arr = ["x", "y", "z", "a", "b", "c"];
var tgtArr = [{val:"a"}, {val:"b"}]; It does not need to be as lengthy as Array `arr`
This is what I have tried
var dest = new Array(arr.length);
for(var i = 0; i < arr.length; i++){
for(var k = 0; k < tgtArr.length; k++){
dest[i] = dest[i] || [];
if(tgtArr[k].val == arr[i]){
dest[i] = arr[i];
}
}
}
console.log(dest);
My Expected output is (for above tgtArr value)
[{}, {}, {}, {val:"a"}, {val:"b"}, {}];
if tgtArr is empty Array
[{},{},{},{},{},{}]
Here is the fiddle. Any alternative for this, it seems not a good way to me as I am iterating through the entire array everytime.
Short:
var result = arr.map(function(x) {
return tgtArr.some(function(o) { return o.val == x; }) ? {val:x} : {};
});
This is more efficient:
var set = {};
tgtArr.forEach(function(obj, i) {
set[obj.val] = true;
});
var result = arr.map(function(x) {
return x in set ? {val:x} : {};
});
This is the same as Paul's answer, but with a loop instead of map. It collects the keys first based on the val property, then creates a new array either with empty objects if the key isn't in tgtArr, or copies a reference to the object from tgtArr if it is:
function newArray(arr, tgtArr) {
var keys = {},
i = tgtArr.length,
j = arr.length,
newArr = [];
// Get keys
while (i--) keys[tgtArr[i].val] = tgtArr[i];
// Make new array
while (j--) newArr[j] = arr[j] in keys? keys[arr[j]] : {};
return newArr;
}
It should be efficient as it only traverses each array once.
var dest = new Array(arr.length);
for(var i = 0; i < arr.length; i++){
dest[i] = {}
for(var k = 0; k < tgtArr.length; k++){
if(tgtArr[k].val == arr[i]){
dest[i] = tgtArr[k];
}
}
}
console.log(dest);
I like using map rather than loops for this kind of thing (Fiddle):
var result = arr.map(function(x) {
var match = tgtArr.filter(function(y) {
return y.val == x;
});
if (match.length == 1) return match[0];
else return {};
});
This is a possibly inefficient, in that it traverses tgtArr for every item in arr, so O(n*m). If needed, you could fix that by pre-processing tgtArr and converting it to a hash map (Fiddle). This way you've got an O(n+m) algorithm (traverse each array once):
var tgtMap = {};
tgtArr.forEach(function(x) { tgtMap[x.val] = x; })
var result = arr.map(function(x) {
var match = tgtMap[x];
return match || {};
});
var tmp = {};
for (var i = 0; i < tgtArr.length; i++) {
tmp[tgtArr[i].val] = i;
}
var dest = [];
for (var i = 0; i < arr.length; i++) {
var obj= tmp[arr[i]] === undefined ? {} : tgtArr[tmp[arr[i]]];
dest.push(obj);
}
DEMO