var sampleArray = [[1,2,3,4],
[5,6,7,8],
[9,10,11,12],
[13,14,15,16],
[17,18,19,20]
];
function printSpiral(myArray, clockwise) {
//anti-clockwise:
//1,5,9,13,17, 18,19,20, 16,12,8,4, 3,2, 6,10,14, 15,11,7
if(!clockwise) {
myArray = transpose(myArray)
//console.log(myArray)
}
var rows = myArray.length;
var cols = myArray[0].length;
if(rows <= 1) {
return myArray[0];
}
if(cols === 0) {
return myArray[0];
}
var firstRow = myArray[0];
var newMatrix = [];
var newRow;
var rowIdx;
var colIdx = myArray[1].length - 1;
for(colIdx; colIdx >=0; colIdx--) {
newRow = [];
for(rowIdx = 1; rowIdx < rows; rowIdx++) {
newRow.push(myArray[rowIdx][colIdx])
//console.log(newRow)
}
newMatrix.push(newRow)
}
//console.log(newMatrix)
firstRow.push.apply(firstRow,printSpiral(newMatrix));
//console.log(firstRow)
return firstRow
//return newMatrix
// Spiral Order
// 1,2,3,4, 8,12,16,20, 19,18,17, 13,9,5, 6,7, 11,15, 14, 10
}
var result = printSpiral(sampleArray, false);
console.log(result)
I am trying to print the array spirally but anticlockwise. I have tried to transpose the matrix but it doesn't help how do I print the following array.
//1,5,9,13,17, 18,19,20, 16,12,8,4, 3,2, 6,10,14, 15,11,7
Please help
Its not very elegant, but here's the juiste of the algorithm:
<script>
var array = [[1,2,3,4],
[5,6,7,8],
[9,10,11,12],
[13,14,15,16],
[17,18,19,20]];
function spiral(array) {
var list = [];
var array = array[0].map(function(col, i) {
return array.map(function(row) {
return row[i]
})
});
list.push(array[0]);
array.shift()
while (typeof array[0] !== 'undefined'){
var array = array[0].map(function(col, i) {
return array.map(function(row) {
return row[i]
})
});
array.reverse();
list.push(array[0]);
array.shift();
}
return list
}
var list = spiral(array)
document.writeln(list);
</script>
basically the idea is as follows, a rotate 90 degrees counterclockwise is done with a transpose and flip. then we pop the top row, and do it again.
so we transpose the array, array.reverse to flip it, push our row into a list, array.shift to pop the row, repeat.
Also the main benefit of this method is that it wont care what the dimensions of your array are. they can be asymmetric or not.
Related
Given an array I want to find the largest sub array by the length i.e
var table = [
["Protein",["Grilled Chicken","Lamb"]],
["Fats",["rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr"]],
["Vegatables",["Carrots","Eggs","Milks","Peppers"]]
];
I want it to return ["Carrots","Eggs","Milks","Peppers"]
Heres my code
function findBiggestSubArray(array){
var biggestArrayIndex = 0;
for(var i=0;i<array.length;i++){
if(i === (array.length-1)){
//We have reached the end of the array then return the array
console.log("Reached the End");
return array[biggestArrayIndex];
} else {
if(!array[biggestArrayIndex][1].length >= array[i][1].length){
biggestArrayIndex = i;
}//End of Inner else block
}//End of Outer else block
}//End of forloop
}
General solution, to find the most largest array in an array-structure:
I would do it with recursion, so the most biggest Array will be found, in any depth..
/**
* array -> The array to check,
* biggestArray -> The most biggestArray found so far
*/
function findBiggestArray(array, biggestArray){
biggestArray = biggestArray || [];
if (array.length > biggestArray.length)
biggestArray = array;
for (var i = 0; i < array.length; i++) {
if (array[i] instanceof Array)
biggestArray = findBiggestArray(array[i],biggestArray)
}
return biggestArray;
}
var multiArray = [
["1", "2", ["234", "334"]],
[1,2,3,4,5, [1,2,3,4,5,6,7,7]]
]
var biggest = findBiggestArray(multiArray)
console.log(biggest)
// This also works!
console.log(findBiggestArray([1, [1,2,3]]))
Oneliner for this special case
// Sort the array by the length of the subarray at position 1, and return the first item
var category = table.sort(function(a, b) { return b[1].length - a[1].length })[0]
// ES6-Syntax
var category = table.sort((a, b) => b[1].length - a[1].length)[0]
category // => ["CategoryName", [ITEMS..]]
I would do this way (see the comments in the code for explanation):
var table = [
["Protein", ["Grilled Chicken", "Lamb"]],
["Fats", ["rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr"]],
["Vegatables", ["Carrots", "Eggs", "Milks", "Peppers"]]
];
function findBiggestSubArray (array) {
// Initialise empty array.
var bigSubArray = ["", []];
// Loop through the given array.
for (var i = 0; i < array.length; i++) {
// Check if the current biggest one is bigger than the saved array.
if (array[i][1].length > bigSubArray[1].length) {
// If bigger, replace it with current array.
bigSubArray = array[i];
}
}
// Return the biggest sub array.
return bigSubArray[1];
}
console.log(findBiggestSubArray(table));
I have a bi-dimensional array made of 0s and 1s.
I need to 'crop' the array so there are no rows / columns that only have 0s in them.
This is how I created the array.
var image = [];
for (y = 0; y < height; y++)
{
image[y] = [];
}
Image example of the array.
And this is what I need the array to be cropped to.
First you should clean the rows by detecting if a an array is full of zeros.
You can use Array.prototype.every.
Example :
This function return is an array is empty or not.
function isEmpty(arr) {
return arr.every(function(item) {
return item===0;
});
}
And you can write an algorithm that detect each rows from 0 until you have a not empty line. And you make the same thing from the end of the array.
After cleaning the rows, you do the do the same thing for cols, and using the same algorithm by using a function that give you each cols as an array.
Here is a complete example that do the job :
var arr = [
[0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0],
[0,0,1,1,1,0,0,0,0],
[0,0,1,0,1,0,0,0,0],
[0,0,0,0,0,0,0,0,0],
[0,0,1,1,1,0,0,1,0],
[0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0]
];
function cleanRows(arr) {
var i=0;
var j=arr.length-1;
while(i<arr.length && isEmpty(arr[i])) {
i++;
}
while(j>i && isEmpty(arr[j])) {
j--;
}
return arr.slice(i,j+1);
}
function cleanCols(arr) {
var i= 0, j=arr[0].length-1;
while(i<j && isEmpty(getCol(arr,i))) {
i++;
}
while(j>i && isEmpty(getCol(arr,j))) {
j--;
}
j++;
// clear each line
return arr.map(function(row) {
return row.slice(i,j);
})
}
function getCol(arr,colIndex) {
return arr.map(function(item) {
return item[colIndex];
});
}
function isEmpty(arr) {
return arr.every(function(item) {
return item===0;
});
}
var newArr = cleanRows(arr);
newArr = cleanCols(newArr);
console.log(newArr);
I have this input sample:
var c1 = "s_A_3";
var c2 = "s_B_10";
var c3 = "s_B_9";
var c4 = "s_C_18";
var c5 = "s_C_19";
var c6 = "s_C_20";
Which can easily be concatenated to:
var keypairs = ["A_3","B_10","B_9","C_18","C_19","C_20"];
And I want to convert this to a multidimensional array like this:
var groupArray = [["A",[3]],["B",[10,9]],["C",[18,19,20]]];
It's like a kind of card-sorting. How can I achieve this?
Maybe something like this:
function makeGroups(arr) {
var result = [], prev;
for(var i = 0; i < arr.length; i++) {
var x = arr[i].split("_");
if (prev !== x[0]) {
prev = x[0];
result.push([prev, []]);
}
result[result.length - 1][1].push(x[1]); // or .push(parseInt(x[1], 10))
}
return result;
}
var keypairs = ["A_3","B_10","B_9","C_18","C_19","C_20"];
console.log(makeGroups(keypairs));
// [["A",["3"]],["B",["10","9"]],["C",["18","19","20"]]]
Demonstration
The above method assumes the groups will be contiguous (e.g. all B_ elements appear together). In case your input may be out of order, you can tweak this algorithm to still group all elements together regardless of where they appear in the input:
function makeGroups(arr) {
var result = [], keys = {};
for(var i = 0; i < arr.length; i++) {
var x = arr[i].split("_");
if (!(x[0] in keys)) {
keys[x[0]] = [];
result.push([x[0], keys[x[0]]]);
}
keys[x[0]].push(x[1]); // or .push(parseInt(x[1], 10))
}
return result;
}
var keypairs = ["A_3","B_10","C_18","C_19","C_20","B_9"];
console.log(makeGroups(keypairs));
// [["A",["3"]],["B",["10","9"]],["C",["18","19","20"]]]
Demonstration
When you need to mention "key value pairs" in a JS program, it's usually most appropriate to use... key value pairs =D.
function solution(input) {
var kvp = {},
result = [];
input.forEach(function (el) {
var cut = el.split("_"),
alpha = cut[0],
numeric = cut[1],
elsWithSameAlpha = kvp[alpha] = kvp[alpha] || [];
elsWithSameAlpha.push(numeric);
});
Object.keys(kvp).forEach(function (key) {
result.push([key, kvp[key]]);
});
return result;
}
I've got a 'table' of two columns represented as an array. The first column are numbers from 1 to 20 and they are labels, the second column are the corresponding values (seconds):
my_array = [ [ 3,4,5,3,4,5,2 ],[ 12,14,16,11,12,10,20 ] ];
I need the mean (average) for each label:
my_mean_array = [ [ 2,3,4,5 ],[ 20/1, (12+11)/2, (14+12)/2, (16+10)/2 ] ];
// edit: The mean should be a float - the notion above is just for clarification.
// Also the number 'labels' should remain as numbers/integers.
My try:
var a = my_array[0];
var b = my_array[1];
m = [];
n = [];
for( var i = 0; a.length; i++){
m[ a[i] ] += b[i]; // accumulate the values in the corresponding place
n[ a[i] ] += 1; // count the occurences
}
var o = [];
var p = [];
o = m / n;
p.push(n);
p.push(o);
How about this (native JS, will not break on older browsers):
function arrayMean(ary) {
var index = {}, i, label, value, result = [[],[]];
for (i = 0; i < ary[0].length; i++) {
label = ary[0][i];
value = ary[1][i];
if (!(label in index)) {
index[label] = {sum: 0, occur: 0};
}
index[label].sum += value;
index[label].occur++;
}
for (i in index) {
if (index.hasOwnProperty(i)) {
result[0].push(parseInt(i, 10));
result[1].push(index[i].occur > 0 ? index[i].sum / index[i].occur : 0);
}
}
return result;
}
FWIW, if you want fancy I've created a few other ways to do it. They depend on external libraries and are very probably an order of magnitude slower than a native solution. But they are nicer to look at.
It could look like this, with underscore.js:
function arrayMeanUnderscore(ary) {
return _.chain(ary[0])
.zip(ary[1])
.groupBy(function (item) { return item[0]; })
.reduce(function(memo, items) {
var values = _.pluck(items, 1),
toSum = function (a, b) { return a + b; };
memo[0].push(items[0][0]);
memo[1].push(_(values).reduce(toSum) / values.length);
return memo;
}, [[], []])
.value();
}
// --------------------------------------------
arrayMeanUnderscore([[3,4,5,3,4,5,2], [12,14,16,11,12,10,20]]);
// -> [[2,3,4,5], [20,11.5,13,13]]
or like this, with the truly great linq.js (I've used v2.2):
function arrayMeanLinq(ary) {
return Enumerable.From(ary[0])
.Zip(ary[1], "[$, $$]")
.GroupBy("$[0]")
.Aggregate([[],[]], function (result, item) {
result[0].push(item.Key());
result[1].push(item.Average("$[1]"));
return result;
});
}
// --------------------------------------------
arrayMeanLinq([[3,4,5,3,4,5,2], [12,14,16,11,12,10,20]]);
// -> [[3,4,5,2], [11.5,13,13,20]]
As suspected, the "fancy" implementations are an order of magnitude slower than a native implementation: jsperf comparison.
var temp = {};
my_array[0].map(function(label, i) {
if (! temp[label])
{
temp[label] = [];
}
temp[label].push(my_array[1][i]);
});
var result = [ [], [] ];
for (var label in temp) {
result[0].push(label);
result[1].push(
temp[label].reduce(function(p, v) { return p + v }) / temp[label].length
);
}
This function do not sort the resulted array like in your result example. If you need sorting, just say me and i will add it.
function getMeanArray(my_array)
{
m = {}; //id={count,value}
for( var i = 0; i<my_array[0].length; i++){
if (m[my_array[0][i]]===undefined)
{
m[my_array[0][i]]={count:0, value:0};
}
m[ my_array[0][i] ].value += my_array[1][i]; // accumulate the values in the corresponding place
m[ my_array[0][i] ].count++; // count the occurences
}
var my_mean_array=[[],[]];
for (var id in m)
{
my_mean_array[0].push(id);
my_mean_array[1].push(m[id].count!=0?m[id].value/m[id].count:0);
}
return my_mean_array;
}
I have the following array...
var arr = [1,2,3,4,5,6,7,8,9]
I need to convert it to the following...
var newArr = [
[1,4,7],
[2,5,8],
[3,6,9],
];
Is this even possible?
Sure it's possible; something like this should work.
function manipulate(array, amount) {
// The array to return
var ret = [];
// Add the first few values to the array
// ret = [[1],[2],[3]];
for (var i=0;i<amount;i++) {
ret.push([array.shift()]);
}
// Now push the last few values on there.
for (var i=0;array.length;i = ++i % amount) {
ret[i].push(array.shift());
}
return ret;
}
and then call it like;
manipulate(arr, 3);