Why am I not entering this for loop - javascript

Why am I not entering this for loop?
Looks like the for loop isn't processing
let z = [1, 2];
function filter_list(l, z) {
// Why am I not entering the for loop?
let del = [];
for (let i = 0; l.length < i, i++;) {
if (z[i] === l[i]) {
console.log(l)
} else {
l[i].push(del)
console.log(l);
}
}
del = undefined
delete(del);
}
let l = [1, 2, 'a', 'b'];
filter_list(l);

missing semicolon after condition. You have a comma instead.You also have an extra semicolon after incrementation. Also you have the condition flipped like CherryDT stated
change this for(let i = 0; l.length < i, i++;){
to this for(let i = 0; i<l.length; i++){

There are a few bugs in the code that you posted - the order of arguments in the for loop, syntax, passing of variables, etc. I have attempted to explain below.
// note that this function takes two arguments "l" and "z" so they will be limited to the function scope
function filter_list(l, z) {
// this is never being used?
let del = [];
// Why am I not entering the for loop?
// check for i less than l.length
// separate using a semicolon
// prefer using i+=1
for (let i = 0; i < l.length; i+=1) {
if (z[i] === l[i]) {
// this will happen if the same element is in the same position in each array, you probably want to not specify the index?
console.log(l)
} else {
// del is an empty array here, it will just overwrite the index of l
l[i].push(del)
console.log(l);
}
}
// this is probably not needed
del = undefined
// this function is not defined and does nothing since del=undefined
delete(del);
}
// you need to pass two arguments to filter_list(), using different variable names to clarify
let one = [1, 2, 'a', 'b'];
let two = [1, 2];
filter_list(one, two);
If you want to filter one list by another a better way to do it would be to use Array.filter() and Array.includes().
const one = [1, 2, 'a', 'b'];
const two = [1, 2];
const three = one.filter((element) => two.includes(element);

Related

Qn-print and write all array element using recursion in JavaScript cuz i'm new to the concept of recursion i couldn't able to figure out the problem

Here is my code and I know there is some mistake in my code but I'm
new to the concept of recursion.
I think there is a problem cuz I tried to implement the same code as
the C language.
I want my answer to read and print array by using recursion
And I tried to convert the c code into javascript, c++ code into
javascript and lastly in python code into javascript.
var a = [1, 2, 3];
var l = a.length;
var num = 0;
function printArr(a, i, l){
for(var i=0; i<l; i++){
num = a[i];
}
if(i>=l){
return 0;
printArr(a, i+1, l); //<I think in this section I'm having a problem.>
}
}
printArr(a, 0, l);
console.log(num);
No need for that for loop.
Your printArr call should be outside if statement.
var a = [1, 2, 3];
var l = a.length;
//var num = 0; // not needed
function printArr(a, i, l) {
// Base condition - to break out of recursion
// check if index is out of array bounds, if yes return
if (i >= l) {
return;
}
// if not, print the array element at that index
console.log(a[i]);
// call the recursive function with next consecutive index
printArr(a, i + 1, l);
}
printArr(a, 0, l);
Another method would allow us to avoid mucking about with indices at all, destructuring the input array and checking whether the first element is empty:
const printArr = ([x, ...xs]) => {
if (x == null) return null
console .log (x)
return printArr (xs)
}
printArr ([1, 2, 3])
I would personally prefer to write this as a single expression, like this:
const printArr = ([x, ...xs]) =>
x == null ? null : (console .log (x), printArr (xs))

Difference between assign and modify array

I just lost 2 days to find where the bug was in my code on angular2 project, working on service.ts file.
I found it! yeah... no. I just fixed it.
I'm here (on stack) to understand the difference between the working code and the bugged one because on my eye their behaviour is the same.
Here is the bugged:
for (let i = 0; i < quantita; i++) {
this.a.p[inizio + i] = target;
}
Here is the working:
this.a.p = this.a.p.map((giorno, index) => {
if (index >= inizio && index < inizio + quantita) {
return target;
} else {
return giorno;
}
});
this.a is a variable that refer to an array. the bug was that the changes affect not only the selected object of the array, but it applies on another one.
I debugged pretty everything, and this.a was the correct instance, the code is called just once (as it should be) and there isn't other code that makes this change on the object.
I think to gave all the info about the problem, if not tell me please.
When you hold an array in a variable, you hold a reference to the array. If you change a value in an array all references will 'see' the change:
let a = [1, 2, 3];
let b = a; // same array in a different variable
for(let i =0;i< a.length;i++) a[i] = a[i] *2;
console.log(a); // [2;3;6]
console.log(b); // [2;3;6]
If you use map a new array will be created that contains the result of the mapping operation:
let a = [1, 2, 3];
let b = a;
a = a.map(n => n * 2) // new array in a, b still has the same array
console.log(a); // [2;3;6]
console.log(b); // [1;2;3]
You can build a for version that will not change the original array if you create a new array and push into that (although I strongly recommend sticking with map I present this just for the sake of completeness):
let a = [1, 2, 3];
let b = a; // same array in a different variable
let tmp = []
for(let i =0;i< a.length;i++) tmp.push(a[i] *2);
a = tmp;
console.log(a); // [2;3;6]
console.log(b); // [1;2;3]

Finding all subsets of a set, Powerset, recursively by cloning n-1 and adding n to the clones

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.

Remove Duplicate rows in multidimensional array using Javascript

var MyArray = [
[1, "07/28/2014"],
[2, "07/29/2014"],
[3, "07/28/2014"],
[4, "07/30/2014"],
[5, "07/28/2014"],
];
In this array, how to remove the duplicate columns and find count the removed items.
I need individual count for removed items.
like
07/28/2014 is 2 times.
This is my Code:
function(MyArray, search_val)
{
var counter = 0; alert(MyArray.length);
for(var i = 0; i < MyArray.length; i++)
{
if(MyArray[i][0] == search_val)
{
MyArray.splice(i, 1);
counter++;
}
}
alert("counter: "+counter);
return counter;
}
Here are a couple very naive basic solutions. Both of these examples are for demonstration purposes only. Do not use in production code. There are parameter validation and other checks that were left out to simplify the examples. Further, depending on your browser requirements, or available frameworks, there are much faster and better ways to do your equality tests. Think of this as a starting point for more research.
I'll leave it as an exercise to improve these answers.
For your data exclusively, this would work:
var count, isFirst, data = [[1,"07/28/2014"], [2,"07/29/2014"],[3, "07/28/2014"],[1,"07/28/2014"],[4, "07/30/2014"]];
count = 0
/* loop over each element of the array */
for(var x = 0; x < data.length; x++) {
isFirst = true // used to skip the first matching element
/* for each loop iteration, loop over every element in the array */
for(var y = 0; y < data.length; y++) {
/*
check the inner loop element against the outer loop element
to see if they satisfy your equality requirements.
Notice the second set of index operator brackets, this is
how you access the next dimension of the array.
*/
if(data[x][1] === data[y][1]) {
/*
If this is not the first time we've found this match
then this must be a duplicate element, so remove it
*/
if (!isFirst) {
data.splice(y, 1);
count++;
}
isFirst = false // makes sure that future matches are removed
}
}
}
console.log(count);
console.log(data);
For a more general solution one possibility would be to pass in the equality test as an anonymous function:
/* Note, this is the same algorithm as above */
function spliceIf(data, predicate) {
var count = 0, isFirst;
for(var x = 0; x < data.length; x++) {
isFirst = true;
for(var y = 0; y < data.length; y++) {
if (predicate(data[x], data[y])) {
if (!isFirst) {
data.splice(y, 1);
count++;
}
isFirst = false
}
}
}
return count;
}
var items = [[1,"07/28/2014"], [2,"07/29/2014"],[3, "07/28/2014"],[1,"07/28/2014"],[4, "07/30/2014"]];
// Now call the new function and pass in the equality test as the second parameter:
var itemsRemoved = spliceIf(items,
function(a, b) {
/*
This predicate function will be passed to spliceIf. When it
is called from within then spliceIf function, it will be
provided with the inner and outer elements of the loop.
You can then do your equality test however you see fit.
Notice the predicate function must return a value.
This is equivalent to the "data[x][1] === data[y][1]" line
in the example above.
*/
return a[1] === b[1];
}
);
console.log(itemsRemoved);
console.log(items);
Just doing some fiddles, I thought this might help. JSFiddle of Duplicate Remover Function
var data = [
[1, "07/28/2014"],
[2, "07/29/2014"],
[3, "07/28/2014"],
[4, "07/30/2014"],
[5, "07/28/2014"],
];
var data2 = [
[1, "07/28/2014"],
[2, "07/29/2014"],
[3, "07/29/2014"],
[4, "07/29/2014"],
[5, "07/29/2014"],
];
function removeDuplicates(Array){
this._newArray = [];
this.numberOfDuplicates = 0;
this.listDuplicates = [];
//Remove Duplicates
for(i=0;i<Array.length;i++){
for(j=0;j<Array.length;j++){
if(!Array[i][1]) //skip the current loop if index is empty
break;
if(Array[i][1]==Array[j][1] && i!=j){
this.listDuplicates.push(Array[j]);
Array[j]=0;
this.numberOfDuplicates+=1; //increase counter for dupes
}
}
}
//Recreate Array
this.newArray = function(){
for(i=0;i<Array.length;i++){
if(Array[i])
this._newArray.push(Array[i]);
}
return this._newArray;
}
}
var data = new removeDuplicates(data);
console.log(data.newArray());
console.log(data.numberOfDuplicates + " Duplicates");
console.log(data.listDuplicates);
console.log("\n");
var data2 = new removeDuplicates(data2);
console.log(data2.newArray());
console.log(data2.numberOfDuplicates + " Duplicates");
console.log(data2.listDuplicates);

javascript permutation generator with permutation length parameter

I've seen a few generators out there but they all make a squared matrix. For example, you give it a list of three items and it'll assume the output of the length is also three. However, I'd like to specify the items and the length.
Sound like an easy problem can't believe there isn't a library available for it. Would like to avoid writing this myself if there's a tested library out there. Any suggestions would be great.
Example of what i've found
var list = 'abc';
perms = permutations(list);
//you cannot define the length
Example
var list = 'abc';
var length = 3;
perms = permutations(list,length);
console.log(perms);
/* output
a,a,a
a,b,c
a,b,a
a,c,a
c,a,a
...
*/
I would like to be able to change length and should create permutations accordingly
length = 2
a,a
a,b
b,b
b,a
length = 4
a,a,a,a
a,a,a,b
....
You can imagine the length as representing the number of slots. Each slot has N possibilities, given that N is the number of elements in your initial list. So given three values [1,2,3], you will have a total of 3 x 3 x 3 = 27 permutations.
Here's my attempt. Comments included!
var list = [1,2,3];
var getPermutations = function(list, maxLen) {
// Copy initial values as arrays
var perm = list.map(function(val) {
return [val];
});
// Our permutation generator
var generate = function(perm, maxLen, currLen) {
// Reached desired length
if (currLen === maxLen) {
return perm;
}
// For each existing permutation
for (var i = 0, len = perm.length; i < len; i++) {
var currPerm = perm.shift();
// Create new permutation
for (var k = 0; k < list.length; k++) {
perm.push(currPerm.concat(list[k]));
}
}
// Recurse
return generate(perm, maxLen, currLen + 1);
};
// Start with size 1 because of initial values
return generate(perm, maxLen, 1);
};
var res = getPermutations(list, 3);
console.log(res);
console.log(res.length); // 27
fiddle
If you're looking for an answer based on performance, you can use the length of the array as a numerical base, and access the elements in the array based on this base, essentially replacing actual values from the base with the values in your array, and accessing each of the values in order, using a counter:
const getCombos = (arr, len) => {
const base = arr.length
const counter = Array(len).fill(base === 1 ? arr[0] : 0)
if (base === 1) return [counter]
const combos = []
const increment = i => {
if (counter[i] === base - 1) {
counter[i] = 0
increment(i - 1)
} else {
counter[i]++
}
}
for (let i = base ** len; i--;) {
const combo = []
for (let j = 0; j < counter.length; j++) {
combo.push(arr[counter[j]])
}
combos.push(combo)
increment(counter.length - 1)
}
return combos
}
const combos = getCombos([1, 2, 3], 3)
console.log(combos)
For smaller use cases, like the example above, performance shouldn't be an issue, but if you were to increase the size of the given array from 3 to 10, and the length from 3 to 5, you have already moved from 27 (33) combinations to 100,000 (105), you can see the performance difference here:
I wrote a little library that uses generators to give you permutations with custom items and number of elements. https://github.com/acarl005/generatorics
const G = require('generatorics')
for (let perm of G.permutation(['a', 'b', 'c'], 2)) {
console.log(perm);
}
// [ 'a', 'b' ]
// [ 'a', 'c' ]
// [ 'b', 'a' ]
// [ 'b', 'c' ]
// [ 'c', 'a' ]
// [ 'c', 'b' ]

Categories

Resources