In practicing understanding arrays and how to loop through them, I wrote a function to map each row, column and two diagonals into their own key value pair.
Is there a more efficient way of looping through this? I know it's bad practice to use two for loops as it leads to high complexity if the grid were bigger than 3x3.
let board = [
[1,2,3],
[4,5,6],
[7,8,9]
];
const mapper = board => {
let
map = {},
d1 = [],
d2 = [];
for (let i = 0; i < board.length; i++) {
let tmp = [];
// get all rows
map[`R${i}`] = board[i];
// get second diagonals
d2.push(board[i][board.length-1-i]);
for (let j = 0; j < board.length; j++) {
// get all columns
tmp.push(board[j][i]);
// get first diagonals
if (i === j) {
d1.push(board[i][j])
}
}
map[`C${i}`] = tmp;
}
map[`D1`] = d1;
map[`D2`] = d2;
return map;
}
console.log(mapper(board));
The below is arguably clearer, and could be imporved futher by using reduce.
board = [
[1,2,3],
[4,5,6],
[7,8,9]
];
diag = 0; map = {}
board.forEach((row,r,arr) => {
var rows = arr.length-1;
map['R'+r] = row;
map['D'+1] = map['D'+1] || [];
map['D'+2] = map['D'+2] || [];
map['D'+1][diag] = row[diag];
map['D'+2][rows-diag] = row[rows-diag]
diag++;
row.forEach((col,c) => {
map['C'+c] = map['C'+c] || [];
map['C'+c].push(col);
});
});
console.log(map);
Related
For some reason, the manipulated doubleArray below is not shown in the console. Any variables that I declare after the for loop won't show to the console on both cases. Consider that in the first algorithm, there is only one for loop with x being incremented everytime. Whereas, in the second algorithm, it's a nested for loop. Can someone help me fix my error in both algorithms?
First Algorithm:
var isDuplicate = function() {
var helloWorld = [1,2,3,4,3];
var doubleValue = [];
var x = 0;
for (i = 0; i < helloWorld.length; i++) {
x = x + 1;
if (helloWorld[i] === helloWorld[x] && i !== x) {
doubleValue.push(helloWorld[i])
console.log(helloWorld[i]);
} else {
continue;
}
}
console.log(doubleValue);
};
The second Algorithm:
var isDuplicate = function() {
var helloWorld = [1,2,3,4,3];
var doubleValue = [];
for (i = 0; i < helloWorld.length; i++) {
for (x = 1; x < helloWorld.length; i++) {
if (helloWorld[i] === helloWorld[x] && i !== x) {
doubleValue.push(helloWorld[x]);
}
}
}
console.log(doubleValue);
};
In first algorithm, you are only checking if the number at current index is equal to the number at the next index, meaning you are only comparing numbers at consecutive indexes. First algorithm will work only if you have duplicate numbers on consecutive indexes.
In second algorithm, you are incrementing i in both loops, increment x in nested loop, change x = 1 to x = i + 1 and your error will be fixed.
Here's the fixed second code snippet
var isDuplicate = function() {
var helloWorld = [1,2,3,4,3, 1, 2];
var doubleValue = [];
for (let i = 0; i < helloWorld.length; i++) {
for (let x = i + 1; x < helloWorld.length; x++) {
if (helloWorld[i] === helloWorld[x] && i !== x) {
doubleValue.push(helloWorld[x]);
}
}
}
console.log(doubleValue);
};
isDuplicate();
Heres's another way to find the duplicates in an array, using an object. Loop over the array, if current number is present as key in the object, push the current number in the doubleValue array otherwise add the current number as key-value pair in the object.
const isDuplicate = function() {
const helloWorld = [1,2,3,4,3, 1, 2];
const doubleValue = [];
const obj = {};
helloWorld.forEach(n => obj[n] ? doubleValue.push(n): obj[n] = n);
console.log(doubleValue);
};
isDuplicate();
Not entirely sure what you are trying to do. If you are only looking for a method to remove duplicates you can do the following:
const hello_world = [1, 2, 2, 3, 4, 5, 5];
const duplicates_removed = Array.from(new Set(hello_world));
A set is a data object that only allows you to store unique values so, when converting an array to a set it will automatically remove all duplicate values. In the example above we are creating a set from hello_world and converting it back to an array.
If you are looking for a function that can identify all the duplicates in an array you can try the following:
const hello_world = [1, 2, 2, 3, 4, 5, 5];
const duplicates_found = hello_world.filter((item, index) => hello_world.indexOf(item) != index);
The main problem by finding duplicates is to have nested loop to compare each element of the array with any other element exept the element at the same position.
By using the second algorithm, you can iterate from the known position to reduce the iteration count.
var isDuplicate = function(array) {
var doubleValue = [];
outer: for (var i = 0; i < array.length - 1; i++) { // add label,
// declare variable i
// no need to check last element
for (var j = i + 1; j < array.length; j++) { // start from i + 1,
// increment j
if (array[i] === array[j]) { // compare values, not indices
doubleValue.push(array[i]);
continue outer; // prevent looping
}
}
}
return doubleValue;
};
console.log(isDuplicate([1, 2, 3, 4, 3])); // [3]
You could take an object for storing seen values and use a single loop for getting duplicate values.
const
getDuplicates = array => {
const
seen = {}
duplicates = [];
for (let value of array) {
if (seen[value]) duplicates.push(value);
else seen[value] = true;
}
return duplicates;
};
console.log(getDuplicates([1, 2, 3, 4, 3])); // [3]
Your first algorithm doesn't work because it only looks for duplicates next to each other. You can fix it by first sorting the array, then finding the duplicates. You can also remove the x and replace it by ++i in the loop.
var isDuplicate = function() {
var helloWorld = [1,2,3,4,3,6];
var doubleValue = [];
helloWorld = helloWorld.sort((a, b) => { return a - b });
for (i = 0; i < helloWorld.length; i++) {
if (helloWorld[i] === helloWorld[++i]) {
doubleValue.push(helloWorld[i])
console.log(helloWorld[i]);
} else {
continue;
}
}
console.log(doubleValue);
};
isDuplicate();
For the second algorithm loop, you probably meant x++ instead of i++ in the second loop. This would fix the problem.
var isDuplicate = function() {
var helloWorld = [1,2,3,4,3,4];
var doubleValue = [];
for (i = 0; i < helloWorld.length; i++) {
for (x = i + 1; x < helloWorld.length; x++) {
if (helloWorld[i] === helloWorld[x]) {
doubleValue.push(helloWorld[x]);
}
}
}
console.log(doubleValue);
};
isDuplicate()
The first algorithm can't be fixed, it can only detect consecutive duplicates,
in the second algorithm you increment i in both loops.
To avoid the duplicates beeing listed too often, you should start the second loop with i + 1
I need code that takes an array, counts the number of elements in it and returns a set of arrays, each displaying a different combination of elements. However, the starting element should be the same for each array. Better to explain with a few examples:
var OriginalArray = ['a','b','c']
should return
results: [['a','b','c'], ['a','c','b']]
or for example:
var originalArray = ['a','b','c','d']
should return
[['a','b','c','d'], ['a','b','d', 'c'], ['acbd', 'acdb', 'adbc', 'adcb']]
Again note how the starting element, in this case 'a' should always be the starting element.
You can use Heap's algorithm for permutations and modify it a bit to add to result only if first element is equal to first element of original array.
var arr = ['a', 'b', 'c', 'd']
function generate(data) {
var r = [];
var first = data[0];
function swap(x, y) {
var tmp = data[x];
data[x] = data[y];
data[y] = tmp;
}
function permute(n) {
if (n == 1 && data[0] == first) r.push([].concat(data));
else {
for (var i = 0; i < n; i++) {
permute(n - 1);
swap(n % 2 ? 0 : i, n - 1);
}
}
}
permute(data.length);
return r;
}
console.log(generate(arr))
You have to do a .slice(1) to feed the rest of the array to a permutations function. Then you can use .map() to stick the first item to the front of each array in the result of permutations function.
If you will do this job on large sets and frequently then the performance of the permutations function is important. The following uses a dynamical programming approach and to my knowledge it's the fastest.
function perm(a){
var r = [[a[0]]],
t = [],
s = [];
if (a.length <= 1) return a;
for (var i = 1, la = a.length; i < la; i++){
for (var j = 0, lr = r.length; j < lr; j++){
r[j].push(a[i]);
t.push(r[j]);
for(var k = 1, lrj = r[j].length; k < lrj; k++){
for (var l = 0; l < lrj; l++) s[l] = r[j][(k+l)%lrj];
t[t.length] = s;
s = [];
}
}
r = t;
t = [];
}
return r;
}
var arr = ['a','b','c','d'],
result = perm(arr.slice(1)).map(e => [arr[0]].concat(e));
console.log(JSON.stringify(result));
I have two arrays
var arr1 = ['wq','qw','qq'];
var arr2 = ['wq','wq','wq','qw','qw','qw','qw','qq','qq'];
Below what i did is matching arr1 values with arr2. If the array contains same values i pushed the values into newArr.
var newArr = [];
for (var i=0;i<arr1.length;i++) {
newArr[i] = [];
}
for (var i=0;i<arr2.length;i++) {
for (var j=0;j<arr1.length;j++) {
if (arr2[i].indexOf(arr1[j]) != -1)
newArr[j].push(arr2[i]);
}
}
console.log(newArr[1]); //newArr[0] = ['wq','wq','wq'];//In second output array newArr[1] = ['qw','qw','qw','qw'];
Is there any easy way to solve this without using two for loops. Better i need a solution in javascript
Maybe use indexOf():
var count = 0;
for (var i = 0; i < arr1.length; i++) {
if (arr2.indexOf(arr1[i]) != -1) {
count++;
// if you just need a value to be present in both arrays to add it
// to the new array, then you can do it here
// arr1[i] will be in both arrays if you enter this if clause
}
}
if (count == arr1.length) {
// all array 1 values are present in array 2
} else {
// some or all values of array 1 are not present in array 2
}
Your own way wasn't totally wrong, you just had to check if the element was index of the array and not of an element in the array.
var arr1 = ['wq','qw','qq'];
var arr2 = ['wq','wq','wq','qw','qw','qw','qw','qq','qq'];
var newArr = [];
for (var i in arr1) {
newArr[i] = [];
}
for (var i in arr2) {
var j = arr1.indexOf(arr2[i]);
if (j != -1) {
newArr[j].push(arr2[i]);
}
}
This way you removed the nested for loop and it still gives you the result you asked for.
var arr1 = ['wq','qw','qq','pppp'];
var arr2 = ['wq','wq','wq','qw','qw','qw','qw','qq','qq'];
function intersect(a, b) {
var d = {};
var results = [];
for (var i = 0; i
d[b[i]] = true;
}
for (var j = 0; j
if (d[a[j]])
results.push(a[j]);
}
return results;
}
var result_array = intersect(arr1,arr2);
// result_array will be like you want ['wq','wq','wq'];
I have an array:
var myarray = [1,2,3,4,7,9,12,13,14]
I need to group values like so:
var array_1 = 1,2,3,4
var array_2 = 7
var array_3 = 8
var array_4 = 12,13,14
I need to find a sequences with an arithmetic progression and seperate from other values.
Any ideas?
Check out this solution
function explode(myarray)
{
var multi = [];
var i = j = 0;
for ( key in myarray )
{
if((myarray[key-1]) != (myarray[key]-1))
{
i++;
j=0;
}
if(j==0)
multi[i] = [];
multi[i][j] = myarray[key];
j++;
}
return multi;
}
It returns a multidimentionnal array that you can use in your example like this
var myarray = [1,2,3,4,7,9,12,13,14];
var multi_array = explode(myarray);
var array_1 = multi_array[0];
var array_2 = multi_array[1];
var array_3 = multi_array[2];
var array_4 = multi_array[3];
New update :
You can also remove the j index and use .push to add new elements to your array
function explode(myarray)
{
var multi = [];
var i = 0;
for ( key in myarray )
{
if((myarray[key-1]) != (myarray[key]-1))
i++;
if(!multi[i])
multi[i] = [];
multi[i].push(myarray[key]);
}
return multi;
}
The following seems to work, but displays a slightly different output than the one you expect.
In your example, I think 7 and 9 should be grouped (any sequence of two items is an arithmetic
progression after all). Or if they are not grouped, then 12 should not be grouped with 13 and
14 either, since 12-9 != 13-12
function split(arr) {
if (arr.length < 2) {
return;
}
var delta = undefined;
var start = 0;
for (var idx = 1; idx < arr.length; idx++) {
if (delta === undefined) {
delta = arr[idx] - arr[idx - 1];
}
if (arr[idx] - arr[idx - 1] != delta) {
alert("subarray " + arr.slice(start, idx));
start = idx;
delta = undefined;
}
}
alert("subarray from" + arr.slice(start, arr.length));
}
split([1,2,3,4,7,9,12,13,14]);
arrays = Array();
var c = 0;
array[c][] = myarray[0]);
for (var i = 1; i<myarray.length; i++) {
if (myarray[i-1] +1 != myarray[i])
c++;
array[c][] = push(myarray[i]);
}
not sure the array syntax (might mix up languages here) is correct or whether I understand your problem fully.
Hey i have a simple question i cant find an answer,
i´m trying to generate some raw-data for a chart
lets say i have an array like :
[1,0,0,1,2,0]
is there a way to make an array out of it that has nested arrays that represent the count of duplicate entrys ?
[[0,3],[1,2],[2,1]]
here is some code that does the trick, but saves the count as objects
var array = [1,0,0,1,2,0];
var length = array.length;
var objectCounter = {};
for (i = 0; i < length; i++) {
var currentMemboerOfArrayKey = JSON.stringify(array[i]);
var currentMemboerOfArrayValue = array[i];
if (objectCounter[currentMemboerOfArrayKey] === undefined){
objectCounter[currentMemboerOfArrayKey] = 1;
}else{
objectCounter[currentMemboerOfArrayKey]++;
}
}
but objectCounter returns them like
{0:3,1:2,2:1}
but i need it as an array i specified above ?
for any help, thanks in advance
Try
var array = [1, 0, 0, 1, 2, 0];
function counter(array) {
var counter = [],
map = {}, length = array.length;
$.each(array, function (i, val) {
var arr = map[val];
if (!arr) {
map[val] = arr = [val, 0];
counter.push(arr);
}
arr[1] += 1;
})
return counter;
}
console.log(JSON.stringify(counter(array)))
Demo: Fiddle
You can turn your object into an array easily:
var obj = {0:3,1:2,2:1};
var arr = [];
for (var key in obj) {
// optional check against Object.prototype changes
if (obj.hasOwnProperty(key)) {
arr.push([+key, obj[key]]);
}
}
Note: The object keys are strings, so i converted them back to numbers when placed in the array.
Functional way of doing this, with Array.reduce and Array.map
var data = [1,0,0,1,2,0];
var result = data.reduce(function(counts, current) {
counts[current] = current in counts ? counts[current] + 1: 1;
return counts;
}, {});
result = Object.keys(result).map(function(current){
return [parseInt(current), result[current]];
});
console.log(result);
Output
[ [ 0, 3 ], [ 1, 2 ], [ 2, 1 ] ]
Try:
var data = [1,0,0,1,2,0];
var len = data.length;
var ndata = [];
for(var i=0;i<len;i++){
var count = 0;
for(var j=i+1;j<len;j++){
if(data[i] == data[i]){
count ++;
}
}
var a = [];
a.push(data[i]);
a.push(count);
ndata.push(a);
}
console.log(ndata)
DEMO here.
First you need to map the array to an associative object
var arr = [1,0,0,1,2,0];
var obj = {};
for (var i = 0; i < arr.length; i++) {
if (obj[arr[i]] == undefined) {
obj[arr[i]] = 0;
}
obj[arr[i]] += 1;
}
Then you can easily turn that object into a 2d matrix like so:
arr = [];
for (var k in obj) {
arr.push([k, obj[k]]);
}
alert(JSON.stringify(arr));
Your existing object can be turned into an array with a simple for..in loop. Also your existing code that produces that object can be simplified. Encapsulate both parts in a function and you get something like this:
function countArrayValues(array) {
var counter = {},
result = [];
for (var i = 0, len = array.length; i < len; i++)
if (array[i] in counter)
counter[array[i]]++;
else
counter[array[i]] = 1;
for (i in counter)
result.push([+i, counter[i]]);
return result;
}
console.log( countArrayValues([1,0,0,1,2,0]) );
Demo: http://jsfiddle.net/hxRz2/