0

Background:

I am working on a scraping project using Selenium that gets data from tables on webpages in our Test and Production environments and then stores the data into two separate Array List of String type (one for test/prod). The data are numbers (double) and there are 3 columns and anywhere from 13-16 rows of data. It varies because I am pulling data from over 145 countries and each table is different.

Please not that that this is just an example. The code that I present here is not the Selenium Script I am running.

Issue:

The issue lies when I am trying to convert the data from the two Array Lists that I have into two 2 dimensional arrays. I have worked with very basic 2d arrays before, but only created them off of user input.

Based on the research I have done before, the syntax for converting an ArrayList to an array is:

  ArrayList<String> b = new ArrayList<>();
    b.add("1.50");
    b.add("3.12");
    b.add("5.25%");
    b.add("2.16");
    b.add("4.36");
    b.add("7.76%")
  //This is just a snippet, remember the list would have anywhere from 13-16  
    indices.

  String[] x = b.toArray();

But how do I convert that same list into an 2 dimensional array in the format of

  1.50 3.12 5.25% 
  2.16 4.36 7.76% 

starting a new line every third index?

Mr. Mayonnaise
  • 159
  • 1
  • 2
  • 13
  • so you want every three elements to be inside a single array ? – Ousmane D. Dec 20 '18 at 14:32
  • Yes, the 2 rows above are one 2 dimensional array. – Mr. Mayonnaise Dec 20 '18 at 14:34
  • Very similar to https://stackoverflow.com/questions/47638892/split-list-into-smaller-lists-of-n-size-with-stream – GBlodgett Dec 20 '18 at 14:37
  • Instead of converting your list to an array (which might cause errors for e.g. if something is missing on the page you might end up having data in one array which not belongs together) i would suggest scraping the data from the page to a proper data structure like `List` or create some costom objects. Also look at Jsoup(HTML parser) for a simple way to get data from a website. – Eritrean Dec 20 '18 at 15:06
  • @Eritrean Selenium is the best tool for this seeing that the webpage is dynamic. Also, this is not the end of the project. Converting from list to array will make the next step easier when that time comes. – Mr. Mayonnaise Dec 20 '18 at 15:18
  • I just wanted to say/ask why don't you read the data from the beginning in the right data structure instead of storing it in a list and convert that later? Two steps where only one is needed; regardless which lib/tool you are using. – Eritrean Dec 20 '18 at 15:28

3 Answers3

2

You have to loop the List and add the items to a new one unless you find value with a percentage (%) in it. Then, you create a new List. This solution is based on the % character appearance, not the fixed size of a gap between elements to split which might be an advantage.

List<List<String>> outer = new ArrayList<>();
List<String> inner = new ArrayList<>();

for (String s: b) {
    inner.add(s);
    if (s.contains("%")) {
        outer.add(inner);
        inner = new ArrayList<>();
    }
}

The List<List<String>> outer will contain these values:

[[1.50, 3.12, 5.25%], [2.16, 4.36, 7.76%]]

To convert the structure from List<List<String>> to String[][], you can use or a simple for-loop approach iterating and filling the array.

String[][] array = outer.stream()
   .map(a -> a.stream().toArray(String[]::new))   // List<String> to String[]
   .toArray(String[][]::new);                     // List<String[]> to String[][]
Nikolas Charalambidis
  • 40,893
  • 16
  • 117
  • 183
1

A typical for loop should do:

List<List<String>> accumulator = new ArrayList<>();
for (int i = 0; i < b.size(); i+=3) {
    List<String> temp = new ArrayList<>(b.subList(i, i + 3));
    accumulator.add(temp);
}

accumulator now looks like:

[[1.50, 3.12, 5.25%], [2.16, 4.36, 7.76%]]

note that the above assumes you'll always a list that is a multiple of three, if that it not the case then you can handle it as follows:

List<List<String>> accumulator = new ArrayList<>();
for (int i = 0; i < b.size(); i+=3) {
     List<String> temp = b.stream().skip(i).limit(3).collect(toList());
     accumulator.add(temp);
}

if you strictly require the result to be a String[][] then you can get it as follows:

 String[][] strings = 
        accumulator.stream()
                   .map(l -> l.toArray(new String[0]))
                   .toArray(String[][]::new);
Ousmane D.
  • 54,915
  • 8
  • 91
  • 126
1

You can iterate over your list an add the entries manually in an 2d-array:

String[][] array = new String[b.size()/3][3];
for (int i = 0; i < b.size(); i++) {
  int row = i / 3;
  int col = i % 3;
  array[row][col] = b.get(i);
}

System.out.println(Arrays.deepToString(array));
Benjamin Schüller
  • 2,104
  • 1
  • 17
  • 29
  • Have you ran this code? I have and I just get the arrayList printed in the same format not a 2d array. – Mr. Mayonnaise Dec 20 '18 at 14:49
  • Yes, i tested it. I put the code for the printed array to my answer. The arrayList is still a list. The 2d-array is stored in another variable called array. – Benjamin Schüller Dec 20 '18 at 14:50
  • You don't need to loop, you can test it with a single call to `deepToString` --> `System.out.println(Arrays.deepToString(array));` – Ousmane D. Dec 20 '18 at 14:52