This question already has answers here:
JavaScript variable number of arguments to function
(12 answers)
Closed 7 years ago.
My function needs to accept any number of lists, then output their symmetric difference. sym([1, 2, 3], [5, 2, 1, 4]) should return [3, 5, 4] and sym([1, 2, 5], [2, 3, 5], [3, 4, 5]) should return [1, 4, 5]. How can I deal with the unknown number of arguments? I thought that I could use the single variable args to create a list of lists, but that isn't working.
function isin(num,arra)
{
for (i=0; i<arra.length; i++)
{
if (num == arra[i]){return true;}
}
return false;
}
function sym(args) {
var syms = [];
console.log(args);
for (i=0; i<args.length; i++)
{
var ins = false;
for (j=0; j<args[i].length; j++)
{
for (k=i+1; k < args.length; k++)
{
if(isin(args[i][j], args[k]))
{
ins = true;
}
}
}
if (ins === false)
{
syms.push(args[i][j]);
}
}
return syms;
}
sym([1, 2, 3], [5, 2, 1, 4]);
use arguments, not args
and you dont need to have it in the function definition.
(note: Im assuming the rest of your code works once you actually get what youre expecting passed in)
so:
function sym() {
var syms = [];
console.log(arguments);
for (i=0; i<argumentss.length; i++)
{
var ins = false;
for (j=0; j<arguments[i].length; j++)
{
for (k=i+1; k < arguments.length; k++)
{
if(isin(arguments[i][j], arguments[k]))
{
ins = true;
}
}
}
if (ins === false)
{
syms.push(arguments[i][j]);
}
}
return syms;
}
For arrays with numbers:
function sym() {
var temp = {}, res = [];
for (var q=0; q<arguments.length; ++q) {
for (var w=0; w<arguments[q].length; ++w) {
temp[arguments[q][w]] ^= 1;
}
}
for (var key in temp) {
if (temp[key] === 1) {
res.push(+key);
}
}
return res;
}
console.log(sym([1, 2, 3], [5, 2, 1, 4]), sym([1, 2, 5], [2, 3, 5], [3, 4, 5]))
Es6 introduces rest paramters. You can use it instead of arguments object.
function logAllArguments(...args) {
for (var arg of args) {
console.log(arg);
}
}
logAllArguments(1,2,3)
Within in each function scope you have access to the arguments object . Any parameters you pass in will available inside of it. You can convert the arguments object to an array using Array.prototype.slice.apply(null,arguments) , and iterate over it.
Related
I am working on a 4x4 sudoku program. I am trying to loop through the column of 2d array and returning false if an elements is not present otherwise return true. I have checked using console.log and my function is only looping through the first item and returning true.
Here is my code:
function linearSearch(array, item) {
var n = array.length;
for (var i = 0; i < n; i++) {
if (array[i] == item) {
return true;
}
}
return false;
}
function checkColumn(puzzle, j) {
//first make an array out of the values stored in column j
let check = [];
//call linearSearch on the array of column
//values for all values of k from 1 to 4
for (var i = 0; i < puzzle.length; i++) {
check.push(puzzle[i][j]);
}
console.log(check);
for (var i = 0; i < check.length; i++) {
if (linearSearch(check, check[i])) {
console.log(i, check[i])
return true;
}
}
return false;
}
var puzzle1 = [
[1, 2, 3, 4],
[2, 3, 4, 1],
[2, 3, 4, 1],
[4, 1, 2, 3]
];
console.log(checkColumn(puzzle1, 2));
var puzzle = [
[1, 2, 3, 4],
[2, 3, 4, 1],
[3, 4, 1, 2],
[4, 1, 2, 3]
];
console.log(checkColumn(puzzle, 1));
any help would be appreciated thanks
In checkColumn in the second loop, you put return true that breaks the loop because your linearSearch return true allways:
for (var i = 0; i < check.length; i++) {
if (linearSearch(check, check[i])) {
console.log(i, check[i])
return true;
}
}
I am trying to write a function that will take an array and n as parameters,
it will return all subsets of that array with n elements, have tried a couple things, couldn't yet succeed.
thanks to whoever put it here, this functions is way too complicated and doesn't do the job, basically what I tried to do here is to pick out one element from a 4 element array to create its 3 element subsets. It doesn't even take N as parameter. it returns all 3 element subsets but also identical ones, so I have to filter them out as well, in any case I will keep trying.
function findSubsets(array) {
var answers = [];
var firstArray = array;
for (i = 0; i < array.length; i++) {
array = firstArray;
for (var k = 0; k < array.length; k++) {
if (k != i) {
var subset = array.splice(k, 1);
answers.push(array); array.splice(k, 0, subset[0]);
}
}
}
}
That not as complicated as it seems. This one is optimized because it doesn't creates useless temporary arrays during the process.
function findSubsets(array, n) {
var answers = [];
for(var i = 0 ; i < array.length ; i += n) {
answers.push(array.slice(i, i + n));
}
return answers;
}
findSubsets([1, 2, 3, 4, 5, 6, 7, 8, 9], 2) // --> [[1, 2], [3, 4], [5, 6], [7, 8], [9]]
findSubsets([1, 2, 3, 4, 5, 6, 7, 8, 9], 3) // --> [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
You can try this solution
var subsetArray = (function() {
return {
getResult: getResult
}
function getResult(array, n) {
function isBigEnough(value) {
return value.length === n;
}
var ps = [
[]
];
for (var i = 0; i < array.length; i++) {
for (var j = 0, len = ps.length; j < len; j++) {
ps.push(ps[j].concat(array[i]));
}
}
return ps.filter(isBigEnough);
}
})();
var arr = [1, 2, 3, 4,5,6,7,8,9];
console.log(subsetArray.getResult(arr,2));
I have the following piece of code:
function destroyer(arr) {
for(var i=1; i<arguments.length; i++){
var kill = arguments[i];
arr = arr.filter(function(x){return x != kill;});
}
return arr;
}
console.log(destroyer([1, 2, 3, 1, 2, 3], 2, 3));
It removes the elements from an array which equal the optional arguments. This code gives [1,1] as I expect.
But if I change the 4th line to
arr = arr.filter(function(x){return x != arguments[i];});
I get [1,2,3,1,2,3] instead, when I expect [1,1]. Why is that the case?
Because when you use arguments within the anonymous function, you're accessing arguments of that function, not destroyer().
You will need to copy the arguments of destroyer(), preferably before your loop as follows:
function destroyer(arr) {
var args = arguments;
for(var i=1; i < args.length; i++)
{
arr = arr.filter(function(x){return x != args[i];});
}
return arr;
}
console.log(destroyer([1, 2, 3, 1, 2, 3], 2, 3));
Alternatively, an arrow function can also be used to achieve the same functionality:
function destroyer(arr) {
for(var i=1; i<arguments.length; i++){
arr = arr.filter(x => x != arguments[i]);
}
return arr;
}
console.log(destroyer([1, 2, 3, 1, 2, 3], 2, 3));
I am trying to write a function that prints only the even numbers from a nested array. Here is my attempt and it keeps returning "undefined".
function printEvents(){
var nestedArr = [[1,2,3],[4,5,6],[7,8],[9,10,11,12]];
for (var i = 0; i<nestedArr.length; i++) {
for (var j = 0; j<nestedArr[i]; j++) {
var evenNumbers = nestedArr[i][j]
}
}
if (evenNumbers % 2 == 0) {
console.log(evenNumbers)
}
}
printEvents();
You could use a recursive approach, if the item is an array. You need to move the test for evenness inside of the for loop.
function printEvents(array) {
var i;
for (i = 0; i < array.length; i++) {
if (Array.isArray(array[i])) {
printEvents(array[i]);
continue;
}
if (array[i] % 2 == 0) {
console.log(array[i]);
}
}
}
printEvents([[1, 2, 3], [4, 5, 6], [7, 8], [9, 10, 11, 12], [[[13, [14]]]]]);
Solution with a callback
function getEven(a) {
if (Array.isArray(a)) {
a.forEach(getEven);
return;
}
if (a % 2 == 0) {
console.log(a);
}
}
getEven([[1, 2, 3], [4, 5, 6], [7, 8], [9, 10, 11, 12], [[[13, [14]]]]]);
You just have a couple issues. You need to check the length of your nested arrays and you need to move your code that checks whether a number is even or not inside the array.
var nestedArr = [[1,2,3],[4,5,6],[7,8],[9,10,11,12]];
for (var i = 0; i<nestedArr.length; i++) {
for (var j = 0; j<nestedArr[i].length; j++) {
var evenNumbers = nestedArr[i][j]
if (evenNumbers % 2 == 0) {
console.log(evenNumbers)
}
}
}
You can do this more easy using filter method which accepts a callback method.
var nestedArr = [[1,2,3],[4,5,6],[7,8],[9,10,11,12]];
var mergedArray=[].concat.apply([], nestedArr);
console.log(mergedArray.filter(a => a%2 == 0));
You can use reduce with every for something quick.
var nestedArr = [ [1, 2, 3],[4, 5, 6],[7, 8],[9, 10, 11, 12]];
var sift = nestedArr.reduce(function(r,o) {
o.every(i => i % 2 === 0 ? r.push(i) : true)
return r;
}, []);
console.log(sift);
If you want a one-liner you can use ReduceRight with Filter
var nestedArr = [[1, 2, 3],[4, 5, 6],[7, 8],[9, 10, 11, 12]];
var sift = nestedArr.reduceRight((p, b) => p.concat(b).filter(x => x % 2 === 0), []);
console.log(sift)
My function needs to accept any number of lists, then output their symmetric difference. sym([1, 2, 3], [5, 2, 1, 4]) should return [3, 5, 4] and sym([1, 2, 5], [2, 3, 5], [3, 4, 5]) should return [1, 4, 5]. I am confused by the result of my code - this returns an empty array.
function isin(num,arra)
{
for (var i=0; i<arra.length; i++)
{
if (num == arra[i])
{
return true;
}
}
return false;
}
function sym()
{
console.log("logging args");
console.log(arguments); // logs [Array[3], Array[4]]
var syms = [];
for (var i=0; i<arguments.length-1; i++)
{
var ins = false;
for (var j=0; j<arguments[i].length; j++)
{
for (var k=i+1; k < arguments.length; k++)
{
if(isin(arguments[i][j], arguments[k]))
{
ins = true;
}
}
}
if (ins === false)
{
syms.push(arguments[i][j]);
}
}
return syms;
}
sym([1, 2, 3], [5, 2, 1, 4]);
EDITED: to add some code
Your loop variables are all global, including i. Put a var in front of them (at least before i) and you're done.
The following gets the symmetric difference of two sets. I hope you can get on from there.
function isin(num,arra)
{
for (var i=0; i<arra.length; i++)
{
if (num == arra[i]){return true;}
}
return false;
}
function sym()
{
var j,k,i,l;
var syms = [];
for ( i=0; i<arguments.length; i++)
{
var ins = false;
for (k=i+1; k < arguments.length; k++){
for ( j=0; j<arguments[i].length; j++){
if(!isin(arguments[i][j], arguments[k]))
{
syms.push(arguments[i][j]);
}
}
for ( l=0; l<arguments[k].length; l++){
if(!isin(arguments[k][l], arguments[i]))
{
syms.push(arguments[k][l]);
}
}
}
}
return syms;
}
sym([1, 2, 3], [5, 2, 1, 4]);
my code returns an array of undefined values
This is because when you are pushing onto syms, your for-loop with the j variable has completed. So it is actually at j = <arguments[i].length (now it really is an out-of-bounds index read).
if (ins === false)
{
syms.push(arguments[i][j]); # push "undefined" onto syms.
}
Make sure you put this block of code inside the for (var j=0; j<arguments[i].length; j++) block.
To solve the symmetric difference of multiple arrays, we can start by designing a function which returns the symmetric difference of two arrays
As shown in function sym2(), the main idea of getting the result from sym2(a1,a2) can be divided into two steps: (1). for every elements in array a1[], if a1[j] is not in array a2[] and a1[j] is not in the result array syms[], then a1[j] is pushed to the result array. (!isin(a1[j],syms)can prevent repeating numbers in a1[], such as sym2 ([1,1],[3]) can return [1,3] instead of [1,1,3]. after a1-a2 is done, the second step a2-a1 is performed the same way (2).for every elements in array a2[], if a2[l] is not in array a1[] and a2[l] is not in the result array syms[], then a2[l] is pushed to the result array.
function sym() take a list of arrays, first, we can save all arrays from the arguments to a variable, like arg[array1,array2,array3], and use Array.reduce() function. for example,if arg contains [a1,a2,a3] arg.reduce(function(a,b){return sym2(a,b)}); is executed like following:
syms2(a1,a2)
syms2(syms2(a1,a2),a3)
all code :
function isin(num,arra)
{
for (var i=0; i<arra.length; i++)
if (num == arra[i]){return true;}
return false;
}
function sym2(a1,a2)
{
var j,l;
var syms = [];
for ( j=0; j<a1.length; j++){
if(!isin(a1[j], a2)&&!isin(a1[j],syms))
syms.push(a1[j]);
}
for ( l=0; l<a2.length; l++){
if(!isin(a2[l], a1)&&!isin(a2[l],syms))
syms.push(a2[l]);
}
return syms;
}
function sym(){
var arg=[];
for(var o = 0; o<arguments.length;o++)
arg.push(arguments[o]);
return arg.reduce(function(a,b){
return sym2(a,b);
});
}