Javascript: Multiple Array looping - javascript

TL DR; What is the most efficient way to sort and compare values in a multiple arrays?
Okay, so we'll assume a few constants to make this whole thing simple
var a = [1, 2, 3, 4, 5, 6], b = [0, 9, 8, 7, 6, 88, 99, 77], i, j;
Now if I wanted to see if any value in a is equal to any other value in b I'd have to sort through one of these arrays 6 times. That's a lot of work, and it would seem there should be a more efficient way to do this. For those needing a visual aide here you are ( and yes I know about -- and ++ I just don't like to use 'em ):
for (i = a.length - 1; i > -1; i -= 1) {
for (j = b.length - 1; j > -1; j -= 1) {
if (a[i] === b[j]) {
return b[j];
}
}
}
The B array gets ran through once for EACH element in A. Again, certainly there is a more efficient way to complete this task?
-Akidi

Depends on the size of your input arrays (several tradeoffs there)-- your nested loops are simplest for small inputs like your examples.
If you have huge arrays, and have control over their construction, consider keeping a map (Object in JS) around acting as a lookup set (if you're creating a in a loop anyways, you can build the set in parallel.)
var setA = {};
for (int i = 0; i < a.length; i++) {
setA[a[i]] = true;
}
Then you can see whether something exists in the set by just checking setA[?].
Likewise with B, or with both together, etc, depending on your needs.

Maybe something like this may help?
var a = [1, 2, 3, 9, 5, 0], b = [0, 9, 8, 7, 6, 88, 99, 77];
var a_dict = {}, l = a.length;
for (var i=0; i < l; i++) {
a_dict[a[i]] = 1;
}
l = b.length;
for (var i=0; i < l; i++) {
if(!!a_dict[b[i]]){
console.log(b[i]);
}
}
You can convert one array to "dict-like" object and compare others with it...

Related

Javascript for loop and splice function

Good day, I have been trying to solve JS problem where I have an array a = [1, 1, 1, 2, 1, 3, 4]. I have to loop through an array and remove every three elements ie (1,1,1) do some logic, then the next three (1,1,2), and so on.
I have used for loop and splice
a = [1, 1, 1, 2, 1, 3, 4]
tuple = ()
for(j=0; j < a.length; j++){
tuple = a.splice(j, 3)
}
However, loop would not go beyond first round of (1,1,1).
What would be the correct way to loop through this array and remove sets of every three elements.
thank you.
Splice return removed elements from base array in given range. You probable want to use slice which only copy them and doesn't change primary array. You can also check this solution.
let a = [1, 1, 1, 2, 1, 3, 4];
for (j = 0; j < a.length; j++) {
if ( j < a.length - 2 ) {
const touple = [ a[j], a[j+1], a[j+2] ]
console.log( touple )
}
}
splice changes the original array and that must be causing your issue.
So, you can use slice which returns a shallow copy of a portion of the original array (without modifying the original array):
const a = [1, 1, 1, 2, 1, 3, 4]
const doLogic = (arr) => {
console.log(JSON.stringify(arr)) // JSON.stringify is only for one-liner print. You can ignore it.
}
for (let i = 0; i < a.length - 2; i++) {
const picked = a.slice(i, i + 3)
doLogic(picked)
}
Or this, if you want to pick the full array when length is less than 3:
if (a.length < 3) {
doLogic(a)
} else {
for (let i = 0; i < a.length - 2; i++) {
const picked = a.slice(i, i + 3)
doLogic(picked)
}
}

How to write my reverse function properly?

i have a problem and i need help for this question.
My reverse function doesn't work the way I want it to.
function reverseArrayInPlace(array){
let old = array;
for (let i = 0; i < old.length; i++){
array[i] = old[old.length - 1 - i];
};
};
let arrayValue = [1, 2, 3, 4, 5];
reverseArrayInPlace(arrayValue);
console.log(arrayValue);
I expect on [5, 4, 3, 2, 1] but i have [5, 4, 3, 4, 5].
Why does it work this way? Please help me understand.
P.S I know about the reverse method.
Variable, with assigned object (array, which is a modified object in fact) - stores just a link to that object, but not the actual object. So, let old = array; here you just created a new link to the same array. Any changes with both variables will cause the change of array.
(demo)
let arr = [0,0,0,0,0];
let bubu = arr;
bubu[0] = 999
console.log( arr );
The simplest way to create an array clone:
function reverseArrayInPlace(array){
let old = array.slice(0); // <<<
for (let i = 0; i < old.length; i++){
array[i] = old[old.length - 1 - i];
};
return array;
};
console.log( reverseArrayInPlace( [1, 2, 3, 4, 5] ) );
P.s. just for fun:
function reverseArrayInPlace(array){
let len = array.length;
let half = (len / 2) ^ 0; // XOR with 0 <==> Math.trunc()
for( let i = 0; i < half; i++ ){
[ array[i], array[len - i-1] ] = [ array[len - i-1], array[i] ]
}
return array;
};
console.log( reverseArrayInPlace( [1, 2, 3, 4, 5] ) );
If you're writing a true in place algorithm, it's wasteful from both a speed and memory standpoint to make an unnecessary copy (as other answers point out--array and old are aliases in the original code).
A better approach is to iterate over half of the array, swapping each element with its length - 1 - i compliment. This has 1/4 of the iterations of the slice approach, is more intuitive and uses constant time memory.
const reverseArrayInPlace = a => {
for (let i = 0; i < a.length / 2; i++) {
[a[i], a[a.length-1-i]] = [a[a.length-1-i], a[i]];
}
};
const a = [1, 2, 3, 4, 5];
reverseArrayInPlace(a);
console.log(a);
Since this is a hot loop, making two array objects on the heap just to toss them out is inefficient, so if you're not transpiling this, you might want to use a traditional swap with a temporary variable.
function reverseArrayInPlace(a) {
for (var i = 0; i < a.length / 2; i++) {
var temp = a[i];
a[i] = a[a.length-i-1];
a[a.length-i-1] = temp;
}
};
var a = [1, 2, 3, 4];
reverseArrayInPlace(a);
console.log(a);
You have in old variable the same array (not by value, but by reference), so if you change any of them you'll have changes in both.
So you should create new array, make whatever you want with them and return it (or just copy values back to your origin array if you don't want to return anything from your function).
It happend like that because:
1) arr[0] = arr[4] (5,2,3,4,5)
2) arr[1] = arr[3] (5,4,3,4,5)
....
n) arr[n] = arr[0] (5,4,3,4,5)
So you can just make a copy (let old = array.slice()) and it'll be woking as you'd expect.

JavaScript - Generating all permutations of an array [duplicate]

This question already has answers here:
Permutations in JavaScript?
(41 answers)
Closed 6 years ago.
I have different arrays, all with numbers, but with different number of elements:
var ar1 = [2, 5];
var ar2 = [1, 2, 3];
I need to get all permutations for each array. The length of the output elements should always be the same as the input array.
This result should be an array of arrays, like this:
for ar1:
[2, 5]
[5, 2]
for ar2:
[1, 2, 3]
[1, 3, 2]
[2, 1, 3]
[2, 3, 1]
[3, 1, 2]
[3, 2, 1]
I don't want a cartesian product, each array should be processed on its own.
All solutions I found so far are creating only order independent arrays, so the result for ar1 is only one array and not two.
The Solution should work for any number of elements in the input array. We can assume that there are no duplicate values in the input array.
You could use for a permutation an iterative and recursive approach until not more elements are to distribute.
function permutation(array) {
function p(array, temp) {
var i, x;
if (!array.length) {
result.push(temp);
}
for (i = 0; i < array.length; i++) {
x = array.splice(i, 1)[0];
p(array, temp.concat(x));
array.splice(i, 0, x);
}
}
var result = [];
p(array, []);
return result;
}
console.log('something bigger [1,2,3,4,5,6,7]');
console.time('t1');
permutation([1, 2, 3, 4, 5, 6, 7]);
console.timeEnd('t1');
console.log(permutation([2, 5]));
console.log(permutation([1, 2, 3]));
.as-console-wrapper { max-height: 100% !important; top: 0; }
Not sure if this is the best way, but it seems to work.
#Nina's solution looks good, but it does a fair bit of array concat & slice, so this might work better for larger sets as it avoids that. I do use an object for duplicate checking, but hashmaps are super fast in JS.
Just curious, so did a performance test.
Doing [1,2,3,4,5,6,7], using #Nina's solution take's 38.8 seconds,.
Doing mine toke 175ms.. So the array concat / slice is a massive performance hit, and the marked duplicate will have the same issue. Just something to be aware off.
var ar1 = [2, 5];
var ar2 = [1, 2, 3];
function combo(c) {
var r = [],
len = c.length;
tmp = [];
function nodup() {
var got = {};
for (var l = 0; l < tmp.length; l++) {
if (got[tmp[l]]) return false;
got[tmp[l]] = true;
}
return true;
}
function iter(col,done) {
var l, rr;
if (col === len) {
if (nodup()) {
rr = [];
for (l = 0; l < tmp.length; l++)
rr.push(c[tmp[l]]);
r.push(rr);
}
} else {
for (l = 0; l < len; l ++) {
tmp[col] = l;
iter(col +1);
}
}
}
iter(0);
return r;
}
console.log(JSON.stringify(combo(ar1)));
console.log(JSON.stringify(combo(ar2)));
console.log('something bigger [1,2,3,4,5,6,7]');
console.time('t1');
combo([1,2,3,4,5,6,7]);
console.timeEnd('t1');

Can anyone tell me why this loop isn't working as it should?

This is for an exercise on codewars.com. The idea is to make a function that takes an array as the first parameter, then deletes each item in sequence defined by the second parameter, so if the second parameter is 3, it'll delete 3 first(counting for this one is supposed to be 1 based, not 0 based), then 6, then 9, then back around to 2, as though all the items were in a circle, then 7 (because 3 and 6 are gone), etc, then return the items in the order in which they were deleted (this pattern is referred to as a Josephus permutation).
So here's my code:
function josephus(items, k) {
var arr = [];
var l = items.length;
var a = k - 1;
for (var i = 0; i < l; i++) {
arr.push(items[a]);
items.splice(a, 1);
a += k - 1 ;
if (a >= items.length) { a = a - items.length; }
}
return arr;
}
It works sometimes. It worked right with josephus([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 1), but then with josephus([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 2), it worked until the last number(5, in this case), then returned null. In fact, most times, it returns null in the place of the last item. Can anyone tell me why it's doing this? If you have a codewars account, you can try it out in its context here: http://www.codewars.com/kata/5550d638a99ddb113e0000a2/train/javascript
Your index re-calculation isn't working. i.e. a = 3, items = [1] a becomes 2, items[2] is undefined. Try this code:
function j(items,k){
var arr = [];
var l = items.length;
var a = k - 1;
for(var i = 0; i<l; i++){
arr.push(items[a]);
items.splice(a, 1);
a += k - 1 ;
a = a % items.length;
}
return arr;
}
Replace
arr.push(items[a]);
with
arr.push(items[a%items.length]);

Can anyone explain me the difference between these two loopings?

http://jsperf.com/jquery-each-vs-for-loop/108
for (var b = a[0], len = a.length; len; b = a[--len]) {
newArray.push(
b
);
}
and
for (var i = 0, len = a.length; i < len; i++) {
newArray.push(
a[i]
);
}
According to jsref, it says the first one is faster. why?
Can anyone explain me the for loop on whats its doing compared to traditional way?
Your first example just does something very different. Check it out:
var a = [1,2,3,4],
newArray = [];
for (var b = a[0], len = a.length; len; b = a[--len]) {
newArray.push(b);
}
> newArray
[1, 4, 3, 2]
Your second example results in the expected [1, 2, 3, 4].
If you need to understand the algorithms, it might be easier when converting the for-notation to while-loops and to expand the decrement and increment operators:
/* first example */
var b = a[0],
len = a.length;
while (len) {
newArray.push(b);
len = len-1;
b = a[len];
}
/* second example */
var i = 0,
len = a.length;
while (i < len) {
newArray.push( a[i] );
i = i+1;
}
I think the major gain of the first loop is that a is being cached in len and then used as a single boolean value : there's a little time to be gained by simplifying the loop condition. However! It will not produce the same array as output.
Assume you have ten elements in a : [0,1,2,3,4,5,6,7,8,9] -- the loop will process a[0] first, then a[--len], which is a[9] in our example. Your end result will be newArray = [0, 9, 8, 7, 6, 5, 4, 3, 2, 1].
So it doesn't matter why it's faster, because it's doing the wrong thing.

Categories

Resources