We have a list of string arrays i.e. List<String[]> (which we got from a csv) which follows the hierarchy:
0000
3000
5000
5000
5000
.
.
.
3900
3000
5000
5000
5000
.
.
.
3900
.
.
.
9999
As you can see, it will always start with 0000 and end with 9999 (think of them as header and footer respectively)
Furthermore, it has equal numbers of 3000 and 3900, with zero to many 5000 records in between.
Input Example:
{
["0000","entry A", entry B", "entry C"....],
["3000","entry1", entry2", "entry3"....], ---
["5000", "entry4", entry 5", "entry 6"...], |
["5000", "entry 7", entry 8", "entry 9"...], |
["5000", "entry 10", entry 11", "entry 12"...], | -> This is one group
["5000", "entry 13", entry 14", "entry 15".....], |
["3900", "entry 16", entry 17", "entry 18"....], ---
["3000","entry19", entry20", "entry 21"....],
["5000", "entry 22", entry 23", "entry 24"...],
["3900", "entry 25", entry 26", "entry 27"...],
["3000","entry 28", entry 29", "entry 30"...],
["3900", "entry 31", entry 32", "entry 33"...],
["9999", "entry X", entry Y", "entry Z"...]
}
The first and last row (i.e. 0000 and 9999) are useless and will not be used.
we have to split this List<String[]> into List<List<String[]>> such that it contains rows from 3000 to 3900
Output:
{
{
["3000","entry1", entry2", "entry3", ...],
["5000", "entry4", entry 5", "entry 6", ...],
["5000", "entry 7", entry 8", "entry 9", ...],
["5000", "entry 10", entry 11", "entry 12", ...],
["5000", "entry 13", entry 14", "entry 15", ...],
["3900", "entry 16", entry 17", "entry 18", ...],
},
{
["3000","entry19", entry20", "entry 21", ...],
["5000", "entry 22", entry 23", "entry 24", ...],
["3900", "entry 25", entry 26", "entry 27", ...],
},
{
["3000","entry 28", entry 29", "entry 30", ...],
["3900", "entry 31", entry 32", "entry 33", ...],
}
}
This is my code so far:
private List<List<String[]>> splitIntoBlocks(List<String[]> rows) {
//get all position of 3000
List<Integer> l1 = IntStream.range(0,rows.size())
.filter(i->rows.get(i)[0].equals("3000"))
.boxed()
.collect(Collectors.toList());
//get all position of 3900
List<Integer> l2 = IntStream.range(0,rows.size())
.filter(i->rows.get(i)[0].equals("3900"))
.boxed()
.collect(Collectors.toList());
List<List<String[]>> res=null;
//split list<string[]> rows into blocks that start with 3000 and end with 3900 and store it in a list
if(l1.size() == l2.size()) {
res = IntStream.range(0, l1.size())
.mapToObj(i->rows.subList(l1.get(i),l2.get(i)+1))
.collect(Collectors.toList());
}
return res;
}
As you can see, I have solved it using streams in roughly 3 stream statements, but I'm not very good at java 8 features. I'm looking for someone to solve this in perhaps 1 or 2 statements. I feel that it is very much possible
P.S. - This is not an interview question, but something I will be using at work.
BufferedReader
and keep a state where a3
has been seen and if not skip any line that doesn’t start with a3
? Is efficiency not a factor? \$\endgroup\$