A bookseller has lots of books classified in 26 categories labeled A, B, ... Z.
-
Each book has a code c of 3, 4, 5 or more capitals letters.
-
The 1st letter of a code is the capital letter of the book category.
-
In the bookseller's stocklist each code c is followed by a space and by a positive integer n (int n >= 0) which indicates the quantity of books of this code in stock.
For example an extract of one of the stocklists could be:
L = {"ABART 20", "CDXEF 50", "BKWRK 25", "BTSQZ 89", "DRTYM 60"}.
or
L = ["ABART 20", "CDXEF 50", "BKWRK 25", "BTSQZ 89", "DRTYM 60"]
You will be given a stocklist (e.g. : L) and a list of categories in capital letters e.g :
M = {"A", "B", "C", "W"}
or
M = ["A", "B", "C", "W"]
and your task is to find all the books of L with codes belonging to each category of M and to sum their quantity according to each category.
For the lists L and M of example you have to return the string (in Haskell/Clojure/Racket a list of pairs):
(A : 20) - (B : 114) - (C : 50) - (W : 0)
my solution according to: https://github.com/delacruzkb/CodeWars-Practice-Java.git
public class StockList {
// 1st parameter is the stocklist (L in example),
// 2nd parameter is list of categories (M in example)
public static String stockSummary(String[] lstOfArt, String[] lstOf1stLetter)
{
String rtnval="";
if(lstOfArt.length != 0 && lstOf1stLetter.length != 0)
{
//Process the summary based on the list of capital letters
for(int i = 0; i < lstOf1stLetter.length; i++)
{
String currentLetter= lstOf1stLetter[i];
int count =0;
//loop through the list of art to find the matching book/stock
for(int q = 0; q < lstOfArt.length; q++)
{
String currentArt = lstOfArt[q];
if( currentArt.substring(0,1).equals(currentLetter) )
{
String[] artValues = currentArt.split(" ");
count += Integer.parseInt(artValues[1]);
}
}
//format the count of the book/stock
String stock = "(" + currentLetter + " : " + count + ")";
if(i != lstOf1stLetter.length - 1)
{
rtnval += stock + " - ";
}
else
{
rtnval += stock;
}
}
}
return rtnval;
}
}
there are two best practices in my opinion using java.stream.collectors
1.
import java.util.Arrays;
import java.util.IntSummaryStatistics;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class StockList {
private static class Book {
public final String category;
public final String code;
public final int quantity;
public Book(String label) {
category = label.substring(0,1);
code = label.split(" ")[0].substring(1);
quantity = Integer.parseInt(label.split(" ")[1]);
}
}
public static String stockSummary(String[] lstOfArt, String[] lstOf1stLetter) {
if (lstOfArt.length == 0 || lstOf1stLetter.length == 0)
return "";
Map<String, Integer> categoryCounts = Arrays.stream(lstOfArt)
.map(Book::new)
.collect(Collectors.groupingBy(book -> book.category,
Collectors.summingInt(book -> book.quantity)));
return Arrays.stream(lstOf1stLetter)
.map(initial -> String.format("(%s : %d)",
initial, categoryCounts.getOrDefault(initial, 0)))
.collect(Collectors.joining(" - "));
}
}
2.
import java.util.Map;
import static java.util.Arrays.stream;
import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.summingInt;
import static java.util.stream.Collectors.joining;
public class StockList {
private static int stockCount(final String s) {
return Integer.valueOf(s.split(" ")[1]);
}
public static String stockSummary(final String[] stock, final String[] categories) {
if (stock.length == 0 || categories.length == 0)
return "";
final Map<String, Integer> counts = stream(stock)
.collect(groupingBy(s -> s.substring(0, 1), summingInt(StockList::stockCount)));
return stream(categories)
.map(s -> "(" + s + " : " + counts.getOrDefault(s, 0) + ")")
.collect(joining(" - "));
}
}
