Chris
Chris

Reputation: 3129

for loop creating columns and rows from an array

I know this is something that I probably learned when I first started, but don't remember how its done because I have never used it. I have an array that I am looping through and am not getting the desired results. I am trying to get the output to go like this..

One Two Three Four
Five Six Seven

But it keeps coming out as
One Two Three Four
One Two Three Four
One Two Three Four
One Two Three Four
One Two Three Four
One Two Three Four
One Two Three Four

Can someone tell me what I have done wrong?

var arr = [
    "One",
    "Two",
    "Three",
    "Four",
    "Five",
    "Six",
    "Seven"
];

for (row = 0; row < arr.length; row++) {
    for (col = 0; col < 4; col++) {
        document.write(arr[col] + "&nbsp;");
    }
    document.write('<br/>');
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Upvotes: 0

Views: 1636

Answers (8)

Trey Eckels
Trey Eckels

Reputation: 348

This might be easier to do using more declarative syntax. You can reduce the contents of the array to a string and if you want to add a break tag on every n element, you can use modulus to test to see if the reduce loop index is the same as n.

The array reduce method provides the previous value, the next value, and the loop index to the function callback.

const arr = [
  "One",
  "Two",
  "Three",
  "Four",
  "Five",
  "Six",
  "Seven"
];

const getString = (dataArr, breakOn) => {
  return dataArr.reduce((prev, next, index) => {
    let str = `${prev} ${next}`;
    
    if (index && index % breakOn === 0) {
      str = `${str}<br />`;
    }
    
    return str;
  }, '');
}

const container = document.getElementById('results');
container.innerHTML = getString(arr, 3);
<div id="results"></div>

Upvotes: 1

Kim Hogeling
Kim Hogeling

Reputation: 661

I'd advice to prevent multiple document.write calls, because it can quickly become a painful bottleneck, if you have a bigger set of data:

var arr = [
  "One",
  "Two",
  "Three",
  "Four",
  "Five",
  "Six",
  "Seven"
];

var table = "";

arr.forEach(function (item, i) {
  table += item + ((i + 1) % 4 !== 0 ? "&nbsp;" : "<br>");
});

document.write(table);
// One&nbsp;Two&nbsp;Three&nbsp;Four<br>Five&nbsp;Six&nbsp;Seven&nbsp;

Also if you're confident with Array.prototype.reduce (and transpile your code for cross browser) then I would suggest to have even less code by reducing the array into a string:

var table = arr.reduce(
  (reduced, item, i) => reduced + item + ((i + 1) % 4 !== 0 ? "&nbsp;" : "<br>")
  , ""
);

Upvotes: 1

CertainPerformance
CertainPerformance

Reputation: 370619

On each iteration, you're starting out starting with col (actually, the array index) at 0:

for (col = 0; col < 4; col++) {

Try adjusting your original arr to account for the desired structure:

const arr = [
  [
    "One",
    "Two",
    "Three",
    "Four",
  ],
  [
    "Five",
    "Six",
    "Seven",
    "Eight",
  ]
];

for (let rowIndex = 0; rowIndex < arr.length; rowIndex++) {
  const row = arr[rowIndex];
  for (let colIndex = 0; colIndex < row.length; colIndex++) {
    document.write(row[colIndex] + "&nbsp;");
  }
  document.write('<br/>');
}

Upvotes: 1

Pierre-Adrien Maison
Pierre-Adrien Maison

Reputation: 610

You shouldn't use two loops but test when you have to put the <br/> : you can test that with the % operator.

for (index = 0; index < arr.length; index++) {
    if (index !== 0 && index % 4 === 0) {
        document.write('<br/>');
    }
    document.write(arr[index] + "&nbsp;");
}

Upvotes: 1

CInvt
CInvt

Reputation: 133

You can make a minor modification:

var arr = [
  "One",
  "Two",
  "Three",
  "Four",
  "Five",
  "Six",
  "Seven"
];

for (index = 0; index < arr.length; index++) {
  document.write(arr[index] + "&nbsp;");
  if ((index + 1) % 4 == 0) {
    document.write('<br/>');
  }
}

//for (col = 0; col < 4; col++) {
//
//  for (row = 0; row < arr.length; row++) {
//    document.write(arr[row] + "&nbsp;");
//  }
//
//  document.write("\n");
//}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Upvotes: 2

Shadowfacts
Shadowfacts

Reputation: 1053

Right now, the element of the array that you're writing to the page is determined the current column (col) which continuously goes from 1 to 4 for each iteration of the outer row loop.

You want to instead iterate over each element of the array and every time it grows greater than the number of columns, insert a line break.

var arr = [
  "One",
  "Two",
  "Three",
  "Four",
  "Five",
  "Six",
  "Seven"
];

for (var index = 0; index < arr.length; index++) {
    document.write(arr[index] + "&nbsp;");

    if ((index + 1) % 4 == 0) {
        document.write("<br/>");
    }
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

This prints each element of the array, and when the index (plus 1, because the array starts at 0, but we need to start at 1) is a multiple of 4 (meaning the end of a row has been reached), a line break tag is written to begin the next row of elements.

Upvotes: 1

Alex Yokisama
Alex Yokisama

Reputation: 1041

for (row = 0, col = 0; row < arr.length; row++, col++) {
  if (col == 4) {
    col = 0;
    document.write('<br/>');
  }
  document.write(arr[row] + "&nbsp;");
}

Upvotes: 2

Jacob
Jacob

Reputation: 78850

You can multiply the row number by the size of a row:

var arr = [
  "One",
  "Two",
  "Three",
  "Four",
  "Five",
  "Six",
  "Seven"
];

const rowSize = 4;

for (row = 0; row < arr.length / rowSize; row++) {

  const startingIdx = row * rowSize;
  for (col = startingIdx; col < arr.length && col < startingIdx + rowSize; col++) {
    document.write(arr[col] + "&nbsp;");
  }

  document.write('<br/>');
}

Upvotes: 2

Related Questions