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(" - ")); } }