how to implement list iteration in javascript - javascript

I have written this code
var items = [
[1, 2],
[3, 4],
[5, 6]
];
function listiteration(list, fromrows, torows, col) {
var newl = list; //making a copy of list
var iterla = [];
for (i = fromrows; i <= torows; i++) {
iterla[i] = [];
for (j = col; j <= col; j++) {
iterla[i][j] = newl[i][j];
}
}
return iterla;
}
console.log(listiteration(items, 1, 2, 1));
result should be
[[4],[6]]
but getting
[ <1 empty item>, [ <1 empty item>, 4 ], [ <1 empty item>, 6 ] ]
how to solve this

You don't need the second for loop. Just create a new list, iterate over the rows and use push function to add the current rows col-th element into the array.
const items = [[1, 2], [3, 4], [5, 6]];
function listiteration(list, fromRows, toRows, col) {
const newList = [];
for (let i = fromRows; i <= toRows; i++) {
newList.push([list[i][col]]);
}
return newList;
}
const newItems = listiteration(items, 1, 2, 1);
console.log(newItems);

You can do this with slice() and map() methods.
var items = [[1, 2], [3, 4], [5, 6]];
function f(list, start, end, col) {
return list.slice(start, end + 1).map(e => [e[col]])
}
const result = f(items, 1, 2, 1)
console.log(result)
You can also add check for arrays.
var items = [[1, 2], 'a', [5, 6], [1, 2]];
function f(list, start, end, col) {
return list
.slice(start, end + 1)
.map(e => Array.isArray(e) ? [e[col]] : e)
}
const result = f(items, 1, 3, 1)
console.log(result)

A simpler approach
var items = [[1, 2], [3, 4], [5, 6]];
function listiteration(list, fromrows, torows, col) {
var ret = [];
for (var i = fromrows; i <= torows; i++) {
ret.push(list[i][col]);
}
return ret;
}
console.log(listiteration(items, 1, 2, 1));

This would be the solution
var items = [ [1, 2], [3, 4], [5, 6] ];
function listiteration(list, start, end, col) {
var result = [];
for ( i = start; i <= end; i++ ) {
result.push( [ list[ i ][ col ] ] )
}
return result;
}
console.log(listiteration(items, 1, 2, 1));

Other answers have given you different ways of doing this, and that's great.
But for learning purposes I've fixed the bug in the one you have done.
All you forgot to do was offset the arrays back to zero..
iterla[i - fromrows][j - col] = newl[i][j];
Example below..
var items = [
[1, 2],
[3, 4],
[5, 6]
];
function listiteration(list, fromrows, torows, col) {
var newl = list; //making a copy of list
var iterla = [];
for (i = fromrows; i <= torows; i++) {
iterla[i - fromrows] = [];
for (j = col; j <= col; j++) {
iterla[i - fromrows][j - col] = newl[i][j];
}
}
return iterla;
}
console.log(listiteration(items, 1, 2, 1));

var items = [
[1, 2],
[3, 4],
[5, 6]
];
function listiteration(list, fromrows, torows, col) {
var newArr = list.splice(fromrows, torows);
var newResult =[];
newArr.map(value=>{
newResult.push([value[col]]);
});
return newResult;
}
console.log(listiteration(items, 1, 2, 1));

Related

Retrieve diagonal values from a 2d array

I'm trying to create a function that retrieves the diagonal values from a 2-d array:
input = [
[1, 2, 3, 4],
[5, 1, 2, 3],
[9, 5, 1, 2]
]
output = [[9], [5, 5], [1, 1, 1], [2, 2, 2], [3, 3], [4]]
I'm having trouble figuring out how to manipulate the indices in a nested loop... This is what I'm currently working with:
const diagonalValues = arr => {
let output = new Array(2*input.length);
for (let i = 0; i < output.length; i++) {
output[i] = [];
if (i < input.length) {
for (j = input.length-1; j>i-input.length; --j) {
console.log(i, j)
}
}
}
}
How can I accomplish this?
You could use get number of rows which is just number of arrays and number of columns which is number of elements in each inner array (assuming all arrays have the same number of elements), and based on that calculate the diagonal matrix.
const input = [
[1, 2, 3, 4],
[5, 1, 2, 3],
[9, 5, 1, 2]
]
const rows = input.length;
const columns = input[0].length;
const total = columns + rows - 1;
const result = [];
for (let i = rows - 1; i >= 0; i--) {
const row = input[i];
for (let j = 0; j < columns; j++) {
const el = input[i][j];
const pos = j + rows - i - 1;
if (!result[pos]) {
result[pos] = []
}
result[pos].unshift(el)
}
}
console.log(JSON.stringify(result))
You can do the same with reduceRight and forEach methods.
let input = [
[1, 2, 3, 4, 4],
[5, 1, 2, 8, 3],
[9, 5, 1, 2, 2],
[9, 5, 1, 2, 1]
]
const result = input.reduceRight((r, a, i) => {
a.forEach((e, j) => {
const pos = j + (input.length - i - 1)
if(!r[pos]) r[pos] = []
r[pos].unshift(e)
})
return r;
}, []);
console.log(JSON.stringify(result))
You can use this algorithm to retrieve the diagonal values from 2d-input array.
const input = [
[1, 2, 3, 4],
[5, 1, 2, 3],
[9, 5, 1, 2]]
let output = []
input.forEach(res => {
res.forEach(resp => {
// if length of array is equel to 1
if (output.filter(x => x == resp).length > 0) {
output.filter(x => x == resp)[0].push(resp)
//if length of array is greater than 1
} else if (output.filter(x => x[0] == resp).length > 0) {
output.filter(x => x[0] == resp)[0].push(resp)
} else {
let temp = []
temp.push(resp)
output.push(temp)
}
})
})
output.forEach(o => console.log(JSON.stringify(o)));
let input = [
[1, 2, 3, 4],
[5, 1, 2, 8],
[9, 5, 1, 2],
[9, 5, 1, 2],
[9, 5, 1, 2],
];
let out = [];
for (let i = 1 - input.length; i < input[0].length; i++) {
let o = [];
let y = Math.max(-i, 0);
let x = Math.max(i, 0);
while (x < input[0].length && y < input.length)
o.push(input[y++][x++]);
out.push(o)
}
out.forEach(o => console.log(JSON.stringify(o)));

Iterate through array to find values that equal a specified sum

I am trying to write a function that will yield the following output:
// Required sum
console.log([3, 4, 2, 1, 2, 3, 6, 0].elementsTheSumTo(6)) // [ [3, 3], [4, 2], [6, 0] ]
console.log([7, 0, 5, 8, 0, 0, 7, 7].elementsThatSumTo(7)) // [ [7, 0], [0, 7], [0, 7], [0, 7] ]
I've tried with,
Array.prototype.elementsThatSumTo = n => {
let result = [];
for (let i = 0; i < this.length; i++) {
for (let j = 0; j < this.length; j++) {
if (j !== i && (this[i] + this[j] === n) {
result.push([ this[i], this[j] ]);
}
}
}
return result;
}
But that's yielding unexpected behavior. I was also thinking of using reduce, but that didn't seem to work either. Not sure how to figure this one out.
You need to remove the elements from the array when matches are found, which can be done with splice. You also need to use a full-fledged function to access the this, the array instance:
Array.prototype.elementsThatSumTo = function(n) {
const arr = this.slice(); // avoid mutating the input array
const result = [];
while (arr.length) {
const num1 = arr.shift();
const num2Index = arr.findIndex(num => num1 + num === n);
if (num2Index === -1) {
continue;
}
result.push([num1, arr[num2Index]]);
arr.splice(num2Index, 1);
}
return result;
}
console.log([3, 4, 2, 1, 2, 3, 6, 0].elementsThatSumTo(6)) // [ [3, 2], [4, 2], [6, 0] ]
console.log([7, 0, 5, 8, 0, 0, 7, 7].elementsThatSumTo(7)) // [ [7, 0], [0, 7], [0, 7], [0, 7] ]
Keep in mind that mutating built-in prototypes is very bad practice. If possible, consider using a standalone function instead:
const elementsThatSumTo = (arrInit, n) => {
const arr = arrInit.slice(); // avoid mutating the input array
const result = [];
while (arr.length) {
const num1 = arr.shift();
const num2Index = arr.findIndex(num => num1 + num === n);
if (num2Index === -1) {
continue;
}
result.push([num1, arr[num2Index]]);
arr.splice(num2Index, 1);
}
return result;
}
console.log(elementsThatSumTo([3, 4, 2, 1, 2, 3, 6, 0], 6)) // [ [3, 2], [4, 2], [6, 0] ]
console.log(elementsThatSumTo([7, 0, 5, 8, 0, 0, 7, 7], 7)) // [ [7, 0], [0, 7], [0, 7], [0, 7] ]
You could take a Map and store the visited elements and cound the occurence.
Array.prototype.elementsThatSumTo = function (sum) {
var map = new Map,
i, l, v
result = [];
for (i = 0, l = this.length; i < l; i++) {
v = this[i];
if (map.get(v)) {
map.set(v, map.get(v) - 1);
result.push([sum - v, v]);
continue
}
map.set(sum - v, (map.get(sum - v) || 0) + 1);
}
return result;
}
console.log([3, 4, 2, 1, 2, 3, 6, 0].elementsThatSumTo(6)) // [ [3, 2], [4, 2], [6, 0] ]
console.log([7, 0, 5, 8, 0, 0, 7, 7].elementsThatSumTo(7)) // [ [7, 0], [0, 7], [0, 7], [0, 7] ]
Array.prototype.elementsThatSumTo = function(n) {
var result = [],
len = this.length;
for (var i = 0; i < len - 1; i++)
for (var j = i + 1; j < len; j++)
if (this[i] + this[j] == n)
result.push([this[i], this[j]]);
return result;
}
console.log([3, 4, 2, 1, 2, 3, 6, 0].elementsThatSumTo(6))
That's because for every number you are also seeing for the combinations that are already covered. Just change (j=0) to (j=(i+1)) in your code it will work fine and you can also ignore the check(j==i) then.
Array.prototype.elementsThatSumTo = function(n) {
let result = [];
for (let i = 0; i < this.length; i++) {
for (let j = (i+1); j < this.length; j++) {
if (this[i] + this[j] === n) {
result.push([ this[i], this[j] ]);
}
}
}
return result;
}
console.log([3, 4, 2, 1, 2, 3, 6, 0].elementsThatSumTo(6)) // [ [3, 3], [4, 2], [6, 0] ]
console.log([7, 0, 5, 8, 0, 0, 7, 7].elementsThatSumTo(7)) // [ [7, 0], [0, 7], [0, 7], [0, 7] ]

how to return the two largest number from each array of an array in JavaScript without using for loops?

function theHighest(data) {
let twoLargest = data.map((x) => {
return x.reduce((prev, curr) => {
return curr
})
})
return twoLargest //returns [3,5,8]
}
console.log(theHighest([[1, 2, 3], [3, 4, 5], [6, 7, 8]]))
The above function can return the largest numbers in each array and if it could return prev along with curr in the same array the job would be done and the desired result would be achieved which is [2,3,4,5,7,8]
How can I return this without using for loops at all?
If I use for loops here is how I do it:
function theHighest(data) {
let highestValues = []
for (let i = 0; i < data.length; i++) {
let first = 0
let second = 0
for (let j = 0; j < data[i].length; j++) {
if (first < data[i][j]) {
second = first;
first = data[i][j];
}
else if (second < data[i][j]) {
second = data[i][j];
}
}
highestValues.push(first, second)
}
return highestValues
}
console.log(theHighest([[1, 2, 3], [3, 4, 5], [6, 7, 8]]))
Thank you!
You could take a copy, sort the array and return the two max values.
function theHighest(data) {
return [].concat(...data.map(a => a.slice().sort((a, b) => a - b).slice(-2)));
}
console.log(theHighest([[1, 2, 3], [3, 4, 5], [6, 7, 8]]));
You need to sort the array as well if it not sorted
function theHighest(data) {
let twoLargest = data.map((x) => {
// Get two largest integers
return x.sort().slice(-2);
})
// Flatten the array
return Array.prototype.concat(...twoLargest);
}
console.log(theHighest([[1, 2, 3], [3, 4, 5], [6, 7, 8]]))
You can also use reduce and sort
var output = arr.reduce( (a, c) => a.concat(c.sort().slice(-2)), [] );
outputs [2,3,4,5,7,8]
Demo
var arr = [[1, 2, 3], [3, 4, 5], [6, 7, 8]];
var output = arr.reduce( (a, c) => a.concat(c.sort().slice(-2)), [] );
console.log( output );

JavaScript array cross random number?

In the array randomly take three numbers, but the number of up and down the left and right non-adjacent (array cross random number)
This is my code, how can I optimize (get the number more evenly)?
Thanks~
array
var a = [
[0, 1],
[2, 3],
[4, 5],
[6, 7]
];
function select() {
var a = [
[0, 1],
[2, 3],
[4, 5],
[6, 7]
];
var lastSelect = -1;
for (var i = 0; i < a.length; i++) {
var index = getRandomNumber(lastSelect, a[i].length);
console.log(a[i][index]);
lastSelect = index;
}
}
function getRandomNumber(lastSelect, max) {
var random = Math.floor(Math.random() * max);
if (random == lastSelect) return getRandomNumber(lastSelect, max);
else return random;
}
select();
Javascript has a modulus operator %, that finds the remainder of division.
var a = [
[0, 1],
[2, 3],
[4, 5],
[6, 7]
];
function select() {
//generating random 0 or 1
var random = Math.round(Math.random());
for (var i = 0; i < a.length; i++) {
console.log(a[i][(i+random)%2]);// 0 or 1
}
console.log("-----------");
}
//test
for(var j=0;j<5;j+=1){
select();
}

Iterating over rows of 2-dimensional array containing arrays of different length

I have a function that picks all elements from a 2-dimensional array by its rows and returns a 1-dimensional array.
The array has a variable amount of columns and rows.
Example:
let arr = [
[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12]
];
Returns:
[1, 5, 9, 2, 6, 10, 3, 7, 11, 4, 8, 12]
The function i came up with:
convertList = (list) => {
let result = [];
let listTotalEntries = R.sum(R.map(R.length)(list));
let mod = R.modulo(R.__, list.length);
let counterRow = -1;
for (let i = 0; i < listTotalEntries; i++) {
if (mod(i) === 0) {
counterRow++;
}
if (list[mod(i)][counterRow]) {
result.push(list[mod(i)][counterRow]);
console.log(list[mod(i)][counterRow]);
}
}
console.log(result);
return result;
};
Question: This function works only with square matrices - how can i make it work with a variable length of the contained arrays?
Example:
let arr = [
[1, 2],
[],
[9, 10, 11, 12]
];
Should return:
[1, 9, 2, 10, 11, 12]
Thanks for your help!
Muff
You had a ramda.js tag in here. With Ramda, it's pretty simple, since there are two functions that will help:
const convertList = compose(flatten, transpose);
convertList(arr); //=> [1, 9, 2, 10, 11, 12]
transpose flips a matrix over its main diagonal, that is, changing rows to columns and vice versa. flatten turns a list of lists into a plain list. So composeing like this essentially creates the equivalent of list => flatten(transpose(list)).
You can see this in action on the Ramda REPL.
I suggest to go step-by-step through the arrays
var arr1 = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]],
arr2 = [[1, 2], [], [9, 10, 11, 12]];
function single(array) {
var r = [],
max = Math.max.apply(null, array.map(function (a) { return a.length; })),
i = 0, j,
l = array.length;
while (i < max) {
for (j = 0; j < l ; j++) {
i in array[j] && r.push(array[j][i]);
}
i++;
}
return r;
}
document.write('<pre>' + JSON.stringify(single(arr1), 0, 4) + '</pre>');
document.write('<pre>' + JSON.stringify(single(arr2), 0, 4) + '</pre>');
Did you try this simple one?
var singleDimensionArr = arr.reduce(function(prev,current){return prev.concat(current)});
For example
[
[1, 2],
[],
[9, 10, 11, 12]
].reduce(function(prev,current){return prev.concat(current)});
outputs [1, 2, 9, 10, 11, 12]
Edit:
Based on the inputs from OP below, since the concatenation needs to happen column wise
var max = Math.max.apply(null, arr.map(function (a) { return a.length; }));
var finalArr = []; for( var i = 0; i < max; i++)
{
for( var j = 0; j < arr.length; j++)
{
arr[j][i] ? finalArr.push(arr[j][i]) : "";
}
}
console.log(arr);
This example makes a big sparse array putting each item where it would belong if the array were square. Then it filters out null values which occur where no input item was present.
let arr = [
[1, 2],
[],
[9, 10, 11, 12]
];
var out = arr.reduce(function(o,n,i,a) {
for (var j=0;j<n.length;j++){
o[a.length * j + i] = n[j];
}
return o;
},[]).filter(function(n) {
return n !== null;
});
alert(JSON.stringify(out));

Categories

Resources