Having a hard time googling for this since I'm not sure what the concepts are called, and all of the "combinations of two arrays/groups" SO posts are not giving me the output I would expect.
Example arrays:
var array1 = ['Bob', 'Tina'];
var array2 = [0, 100];
I can find possible combinations with nested looping through both arrays. But that would give me an output like:
var array1 = ['Bob', 'Tina'];
var array2 = [0, 100];
var options = []
array1.forEach(function (name) {
array2.forEach(function (number) {
options.push([name, number])
})
})
console.log(options);
> [ [ 'Bob', 0 ], [ 'Bob', 100 ], [ 'Tina', 0 ], [ 'Tina', 100 ] ]
this post (Creating Combinations in JavaScript) gives me the output above
But what I'm really looking for would give me arrangements/combinations like this:
[
[['Bob', 0], ['Tina', 0]],
[['Bob', 0], ['Tina', 100]],
[['Bob', 100], ['Tina', 0]],
[['Bob', 100], ['Tina', 100]]
]
And it would need to be able to scale with longer arrays, but 2x2 is the easiest example.
This cartesian example here (Matrix combinations of two arrays in javascript) also gave me broken out strings and not correlated arrangements:
[ { '0': 'B', '1': 'o', '2': 'b' },
{ '0': 'B', '1': 'o', '2': 'b' },
{ '0': 'T', '1': 'i', '2': 'n', '3': 'a' },
{ '0': 'T', '1': 'i', '2': 'n', '3': 'a' } ]
I have been looking through google and SO but I'm hitting roadblocks because I'm not sure what I'm actually looking for.
I hope this might help you to get your actual combination:
var array1 = ['Bob', 'Tina'];
var array2 = [0, 100];
var resultArray = []
for (var i = 0; i < array1.length; i++) {
for (var j = 0; j < array2.length; j++) {
var tempArray = [];
tempArray.push(array1[i]);
tempArray.push(array2[j]);
resultArray.push(tempArray);
}
}
for (var i = 0; i < array2.length; i++) {
for (var j = 0; j < array1.length; j++) {
var tempArray = [];
tempArray.push(array1[j]);
tempArray.push(array2[i]);
resultArray.push(tempArray);
}
}
console.log(resultArray);
I'll give you some hints that you might find helpful. First, I assume you know how to iterate over an array:
var array1 = ['Bob', 'Tina'];
for (var i = 0; i < array1.length; i++) {
// you can access the ith element using array1[i]
// for example:
alert(array1[i]);
}
I also assume you know how to execute nested looping:
var array1 = ['Bob', 'Tina'];
var array2 = [0, 100];
for (var i = 0; i < array1.length; i++) {
for (var j = 0; j < array2.length; j++) {
alert(array1[i] + " " + array2[j]):
}
}
What you may be missing is how to construct a new array:
var five = 5;
var six = 6;
var myArray = [five, six];
You also may be missing the ability to push a new array onto an existing "master" array:
var five = 5;
var six = 6;
var masterArray = [];
for (var i = 0; i < 10; i++) {
masterArray.push([five, six]);
}
Hope this helps, and good luck!
This solves the problem, but don't know how efficient it is - I'll bet there's much better ways of doing it.
var array1 = ['Bob', 'Tina', 'Sam'];
var array2 = [0, 100, 200];
var resultCount = Math.pow(array2.length, array1.length);
var results = new Array(resultCount);
for(var i = 0; i < resultCount; i++) {
results[i] = new Array(array1.length);
}
for(var row = 0; row < resultCount; row++) {
for(var column = 0; column < array1.length; column++) {
var result = row * array1.length + column;
var category = array1.length * Math.pow( array2.length, array1.length - 1 - column);
var idx = ~~(result / category) % array2.length;
results[row][column] = [ array1[column], array2[idx] ];
}
}
console.log(results);
I think you could actually do this in terms of number/string manipulation by thinking of array2 as a radix (each value maps to a digit) and array1 as the number of digits. As long as array2 has 36 or less elements you could convert every number from 0 up to the number of combinations as a string (Number.toString(radix)) and then convert each char from the resulting string back to an index into your arrays.
Related
I'm trying to create a Boggle Solver program and I am having errors with my depth-first-search function. After I iterate through the 'visited' array using a for-loop, my function should return and start going through my trie again. Instead, it continues to print the value that is found in the visited array. The code is displayed below.
// Sample Boggle Dictionary
var boggle_dxctionary = ['apple', 'pickle', 'side',
'sick', 'moo', 'cat',
'cats', 'man', 'super',
'antman', 'godzilla', 'dog',
'dot', 'sine', 'cos',
'signal', 'bitcoin', 'cool',
'kick', 'zapper'
];
// Sample Boggle Board
var boggle_board = [
['c', 'n', 't', ],
['d', 'a', 't', ],
['o', 'o', 'm', ],
];
var column_length = boggle_board[0].length;
var row_length = boggle_board.length;
var trie_node = {
'valid': false,
'next': {}
};
var neighbors_delta = [
[-1, -1],
[-1, 0],
[-1, 1],
[0, -1],
[0, 1],
[1, -1],
[1, 0],
[1, 1],
];
function generate_trie(word, node)
{
if (!(word))
{
return;
}
if ((word[0] in node) == false)
{
node[word[0]] = { 'valid': (word.length == 1),'next': {}};
}
generate_trie(word.slice(1, ), node[word[0]]);
}
function build_trie(boggle_dxct, trie) {
for (var word = 0; word < boggle_dxct.length; word++) {
generate_trie(boggle_dxct[word], trie);
}
return trie;
}
function get_neighbors(row, column)
{
var neighbors = [];
for (var neighbor = 0; neighbor < neighbors_delta.length; neighbor++)
{
var new_row = row + neighbors_delta[neighbor][0];
var new_column = column + neighbors_delta[neighbor][1];
if (new_row >= row_length || new_column >= column_length || new_row < 0 || new_column < 0)
{
continue;
}
neighbors.push([new_row, new_column]);
}
return neighbors;
}
function depth_first_search(row, column, visited, trie, current_word, found_words, board)
{
var row_column_pair = [row, column];
for (var i = 0; i < visited.length; i++) # Infinity loop error
{
var a = visited[i][0];
var b = visited[i][1];
if (row == a && column == b)
{
console.log(a,b);
return;
}
}
var letter = board[row][column];
visited.push(row_column_pair);
if (letter in trie)
{
current_word = current_word + letter;
console.log(current_word)
if (trie[letter]['valid'])
{
console.log("Found word", current_word, "at", row_column_pair);
found_words.push(current_word);
//console.log(visited);
}
var neighbors = get_neighbors(row, column);
for (n = 0; n < neighbors.length; n++)
{
depth_first_search(neighbors[n][0], neighbors[n][1], visited.slice(0), trie[letter], current_word, found_words, board);
}
}
}
function main(trie_node, board) {
trie_node = build_trie(boggle_dxctionary, trie_node);
var found_words = [];
for (r = 0; r < row_length; r++) {
for (c = 0; c < column_length; c++)
{
var visited = [];
depth_first_search(r, c, visited, trie_node, '', found_words, board);
}
}
console.log(found_words);
}
main(trie_node, boggle_board);
The problem in your code is in depth_first_search where you did not define n as a local variable, but as implicit global variable.
Your code will run fine when you replace this:
for (n = 0; n < neighbors.length; n++)
with:
for (var n = 0; n < neighbors.length; n++)
NB: I assume there was a little typo in the input, where "moo" should really be "mood".
I suggest to use a more simplified trie without overhead.
Then iterate the given board and check the actual position and by handing over the root node of trie.
A word is found if end property exists.
function check(i, j, t, found = '') {
const letter = board[i][j];
if (!t[letter]) return;
found += letter
if (t[letter].end) {
words.push(found);
}
for (let [x, y] of neighbors) {
if (i + x < 0 || i + x >= rows || j + y < 0 || j + y >= cols) continue;
check(i + x, j + y, t[letter], found);
}
}
const
dictionary = ['apple', 'pickle', 'side', 'sick', 'moo', 'cat', 'cats', 'man', 'super', 'antman', 'godzilla', 'dog', 'dot', 'sine', 'cos', 'signal', 'bitcoin', 'cool', 'kick', 'zapper'],
board = [['c', 'n', 't'], ['d', 'a', 't'], ['o', 'o', 'm']],
rows = board.length,
cols = board[0].length,
neighbors = [[-1, -1], [-1, 0], [-1, 1], [0, -1], [0, 1], [1, -1], [1, 0], [1, 1]],
trie = dictionary.reduce((trie, word) => {
[...word].reduce((t, c) => t[c] = t[c] || {}, trie).end = true;
return trie;
}, {}),
words = [];
for (let i = 0; i < rows; i++) {
for (let j = 0; j < cols; j++) {
check(i, j, trie);
}
}
console.log(words);
console.log(trie);
.as-console-wrapper { max-height: 100% !important; top: 0; }
This is just a simple javascript exercise that I'm working on.
I'm trying to convert this array...
var array = [
[1,2],
[3,4],
[5,6]
];
into...
array = [1, 2, 3, 4, 5, 6];
by using this nested for loop.
var series;
var storage = [];
for (var i = 0; i < array.length; i++) {
for (var j = 0; j < array[i].length; j++) {
series = array[i][j];
for (var k = 0; k < 6; k++) {
storage[k] = series;
};
};
};
console.log(storage);
With an output of...
//Output: [6, 6, 6, 6, 6, 6]
Why is this the output and how can I fix it?
for (var k = 0; k < 6; k++) { is not required . array[i] will be each of element inside main array , so iterating over array[i] you can access each of the element
var array = [
[1, 2],
[3, 4],
[5, 6]
];
var series;
var storage = [];
for (var i = 0; i < array.length; i++) {
for (var j = 0; j < array[i].length; j++) {
storage.push(array[i][j])
};
};
console.log(storage);
series = array[i][j];
for (var k = 0; k < 6; k++) {
storage[k] = series;
};
Seriously, here you set the same value to each element of the resulting array.
You probably need something like
for(let x of array) {
for(let y of x) {
storage.push(y)
}
}
Or, if your JS machine is experimental enough, simply
var storage = array.flat()
You can use a mix of reduce and concat to achieve what you want in one line
var array = [
[1, 2],
[3, 4],
[5, 6]
];
console.log(array.reduce((a, v) => a.concat(v), []));
As for why your code didn't work, it's mainly down to this bit
for (var k = 0; k < 6; k++) {
storage[k] = series;
};
It would overwrite everything in the array with the last value of series, which in your case would be 6
Array.concat can do this on its own
var merged = [].concat.apply([], array);
var array = [
[1,2],
[3,4],
[5,6]
];
var newArray = [];
for (let i = 0; i < array.length; i++) {
newArray = newArray.concat(array[i]);
}
console.log(newArray)
You can use array.flat()
Reference : flatten
var array = [
[1,2],
[3,4],
[5,6]
];
array.flat();
// 1,2,3,4,5,6....
You could use the ES6 spread syntax like this:
for (let element of array){
storage.push( ... el )
}
storage = [];
for(var i=0; i<array.length; i++)
storage = storage.concat(array[i]);
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/concat
Am trying to print out every first elements of each array followed by next element on the index, this is my progress so far...
var data = ['x', [1, 2, 3,4], ['a', 'b','c', 'd'], ['I', 'II', 'III', 'IV']];
for (var i = 1; i < data.length; i++) {
for (var j = 0; j < 1; j++) {
console.log(data[i][j]);
}
}
my first result is 1aI, how can I print 2bII, 3cIII, 4dIV
Your algorithm should be like this:
For each column:
value = ""
For each row:
combine value with the element
print value
var data = ['x', [1, 2, 3,4], ['a', 'b','c', 'd'], ['I', 'II', 'III', 'IV']];
for (var j = 0; j < data[1].length; j++) {
var value = "";
for (var i = 1; i < data.length; i++) {
value = value + data[i][j];
}
console.log(value);
}
var data = ['x', [1, 2, 3,4], ['a', 'b','c', 'd'], ['I', 'II', 'III', 'IV']];
for (var i = 0; i < data.length; i++) {
output = '';
for (var j = 1; j < 4; j++) {
output += data[j][i];
}
console.log(output);
}
So I have these two questions considering the JavaScript language:
Is there any way to append to an array without using the push() function or any other built in functions in the language?
Is there any way to merge two arrays together without using the concat() function or any other built in functions in the language?
For the first part you can always use the length property of the array, to add the next element:
a = ['a', 'b', 'c', 'd'];
a[a.length] = 'e';
// a is now ["a", "b", "c", "d", "e"]
To do the latter, merge the arrays, without a function you can just loop thru the arrays, should pick the largest one to loop on. But yeah, as the comments state. There's usually not a good reason to do so.
Here are the alternatives for you:
To add the item to the array without push call:
arr[arr.length] = value;
To concatenate one array to another without concat call:
for (var i = 0; i < arr2.length; arr1[arr1.length] = arr2[i++]);
Not sure if this is what you are looking for or why but arr[arr.length] = 1; is the answer both of your questions.
var myArr = [];
myArr[myArr.length] = 1;
myArr[myArr.length] = 2;
myArr[myArr.length] = 3;
var myArr1 = [...]; // has items;
var myArr2 = [...]; // has items;
var mergedArr = [];
for(var i = 0; i < myArr1.length){
mergedArr[mergedArr.length] = myArr1[i];
}
for(var i = 0; i < myArr2.length){
mergedArr[mergedArr.length] = myArr2[i];
}
Yes, you can do so without using .push, concat, or .length. ES6 allows the use of the spread syntax (...):
var arr = [1, 2]; // arr is 1, 2
var arr = [...arr, 3]; // arr is now 1, 2, 3
let arr1 = [1, 2];
let arr2 = [3, 4];
arr = [...arr1, ...arr2]; // arr is now 1, 2, 3, 4
function pop(arr) {
let finalVar = arr[arr.length - 1];
arr.length = arr.length - 1;
return finalVar;
}
I hope this can solve your problem:
const addItem = (arr, ...arguments) => {
for (let i = 0; i < arguments.length; i++) {
arr[arr.length] = arguments[i];
}
return arr;
};
let myArr = [];
console.log(addItem(myArr, 'Chaewon')); // ['Chaewon'])
console.log(addItem(myArr, 'Liz')); // ['Chaewon', 'Liz']);
<html lang="en">
<head>
<script>
let data = [20, 80, 79, 21, 40];
let newEl = 26;
let position = 2;
console.log(data);
for(let i = data.length-1; i >= 0; i--){
console.log(data[i]);
if (i >= position) {
data[i + 1]= data[i];
if (i === position) {
data[i]= newEl;
}
}
}
console.log(data)
</script>
</head>
<body>
</body>
</html>
I have N number of arrays in an array, for now N = 3
[[1,2,3, "a","b"] , [3,4,5,"c"], [6,7,8]...]
I would like for it to return
[[1,3,6], [2,4,7], [3,5,8], ...., ["a","c", ""], ["b", "",""]]
There are lot of solutions of combining two arrays but I want to handle any number of arrays. I would like for it to return above. I am looking to do this without underscore or jquery.
Values=[];
status = [[1,2,3, "a","b"] , [3,4,5,"c"], [6,7,8]];
status_name = status[0]; //take the longest one always
for (i = 0; i < status_name.length; ++i)
{
Values[i] =Array(status_name[i], status[i+1][i]);
}
why not nest loops ?
sth. like this warning pseudocode
Values=[];
status = [[1,2,3, "a","b"] , [3,4,5,"c"], [6,7,8];
status_name = status[0];
for (i = 0; i < status.length; ++i)
{
for (k = 0; k < status[i].length; ++i)
{
Values[i] =Array(status[i][k], status[k+1][k]);
}
}
var originalArray = [[1, 2, 3, "a", "b"], [3, 4, 5, "c"], [6, 7, 8]];
var theValues = new Array();
var actualArray = originalArray.pop();
var maxLength = originalArray.length;
while (actualArray) {
for (var i = 0; i < actualArray.length; i++){
var newArray = theValues[i];
if (!newArray) {
theValues[i] = new Array();
}
theValues[i].push(actualArray[i])
}
actualArray = originalArray.pop();
}
for (var i = 0; i < theValues.length; i++) {
for (var j = maxLength - theValues[i].length; j >= 0; j--) {
theValues[i].push("");
}
}
Conceptually, this is most easily achieved using nested loops;
var a = [[1, 2, 'x'], ['a', 'b'], ['+', '-', 'y', 'z']]; // input array
function transform(a) {
var i, j, // two loops = two variables to iterate with
foundSomething, // a flag so we know to stop
b = []; // output array
i = 0;
do { // loop for i
foundSomething = false;
b[i] = [];
for (j = 0; j < a.length; ++j) { // loop for j
if (i in a[j]) { // something exists at this level of i
foundSomething = true;
b[i].push(a[j][i]);
} else { // nothing here
b[i].push(''); // insert empty string
}
}
++i;
} while (foundSomething);
b.length = b.length - 1; // snip empty end
return b;
}
transform(a); // [[1, "a", "+"], [2, "b", "-"], ["x", "", "y"], ["", "", "z"]]
Sorting required?
a.sort(function (a, b) {return a.length < b.length;}); // bigger arrays first
transform(a); // [["+", 1, "a"], ["-", 2, "b"], ["y", "x", ""], ["z", "", ""]]
If you're always doing this sort, you can further optimise transform i.e. because you know that a[x].length >= a[y].length for all x < y, you don't need to flag whether you found something