Convert Files input to Map of List Map Inside - string

I have input as below from file reading,
1|VegemiteScroll|VS5|3|6.99
2|VegemiteScroll|VS5|5|8.99
3|BlueberryMuffin|MB11|2|9.95
4|BlueberryMuffin|MB11|5|16.95
5|BlueberryMuffin|MB11|8|24.95
6|Croissant|CF|3|5.95
7|Croissant|CF|5|9.95
I wanted to put it in Hashmap using group by as below, Let's consider #1,#2 lines.
Map obj = new HashMap();
obj.put(3,6.99);
obj.put(5,8.99);
List<Map> list = new ArrayList<>();
list.add(obj)
Map<String, List<Map>> map = new HashMap();
map.put("VS5", list);
This is for 1st case, and for second and third case (# 3 to #8),
map.put("MB11", list);
The list contains List of Map as above. Could you please me to put solve this using java8 streams. Thanks in advance!

Here is a solution using Java 8 Streams, groupingBy and other "fancy stuff". For the sake of simplicity, I've assumed that the input is already provided as a String.
private static final int EXPECTED_LINE_ELEMENTS = 5;
private static final int LINE_KEY_INDEX = 2;
private static final int DATA_KEY_INDEX = 3;
private static final int DATA_VALUE_INDEX = 4;
private static Map<String, List<Map<Integer, Float>>> convert(final String input) {
return Stream.of(input.split("\\n")) // split input by new line character
.filter(line -> !line.trim().isEmpty()) // filter out empty lines
.map(line -> line.split("\\|")) // split each line by '|' character
.filter(line -> line.length == EXPECTED_LINE_ELEMENTS) // filter out potential elements containing undesired number of columns
.collect(Collectors.groupingBy(line -> line[LINE_KEY_INDEX])) // convert to map using 3rd column as a key and a list of corresponding lines as values
.entrySet()
.stream()
.collect(
Collectors.toMap(
Map.Entry::getKey, // keep the same key
stringListEntry -> Collections.singletonList(convertLinesToMap(stringListEntry.getValue())) // convert list of lines to a singleton list containing a map
)
);
}
private static Map<Integer, Float> convertLinesToMap(final List<String[]> lines) {
return lines.stream()
.collect(Collectors.toMap(
line -> Integer.valueOf(line[DATA_KEY_INDEX].trim()), // use 4th column as key of the map (mapped to Integer)
line -> Float.valueOf(line[DATA_VALUE_INDEX].trim())) // use 5th column as key of the map (mapped to Float)
);
}
Then, the following:
System.out.println(convert(input));
Should print this:
{ CF =[{3=5.95, 5=9.95, 9=16.99}], VS5 =[{3=6.99, 5=8.99}], MB11 =[{2=9.95, 5=16.95, 8=24.95}]}
PS. As you've written:
Map obj = new HashMap();
obj.put(3,6.99);
obj.put(5,8.99);
I've assumed that you want to have Integers as keys and Floats as values. If this is not the case, you can just update appropriate fragments of convertLinesToMap method.

Below is the code which serves purpose. It is not optimised fully. But it is working.
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
/**
*
*/
/**
* #author KishorRaskar
*
*/
public class Main {
/**
* #param args
* #throws Exception
*/
public static void main(String[] args) throws Exception {
// pass the path to the file as a parameter
File file =
new File("C:\\Data\\FAB\\WorkSpace\\Test\\MyCode\\test.txt");
Scanner sc = new Scanner(file);
List<HashMap> mapList = new ArrayList<>();
HashMap<String, String> dataMap = null;
HashMap<String, List<HashMap<String, String>>> dataMapList = new HashMap<>();
while (sc.hasNextLine()) {
String line = sc.nextLine();
if(null == line || line.isEmpty()) {
continue;
}
String[] dataArray = line.split("\\|");
//System.out.println(Arrays.toString(dataArray));
String dataMapKey = dataArray[3].trim();
String dataMapValue = dataArray[4].trim();
String dataMapListKey = dataArray[2].trim();
if(!dataMapList.containsKey(dataMapListKey)) {
dataMapList.put(dataMapListKey, new ArrayList<>());
dataMapList.get(dataMapListKey).add(new HashMap<>());
}
dataMapList.get(dataMapListKey).get(0).put(dataMapKey, dataMapValue);
//System.out.println(line);
}
System.out.println("###############################");
System.out.println(dataMapList);
System.out.println("###############################");
}
}
Input : test.txt
1 | Vegemite Scroll| VS5 | 3 | 6.99
2 | Vegemite Scroll| VS5 | 5 | 8.99
3 | Blueberry Muffin| MB11 | 2 | 9.95
4 | Blueberry Muffin| MB11 | 5 | 16.95
5 | Blueberry Muffin| MB11 | 8 | 24.95
6 | Croissant| CF | 3 | 5.95
7 | Croissant| CF | 5 | 9.95
8 | Croissant| CF | 9 | 16.99
Output:
###############################
{CF=[{3=5.95, 5=9.95, 9=16.99}], MB11=[{2=9.95, 5=16.95, 8=24.95}], VS5=[{3=6.99, 5=8.99}]}
###############################

Related

ANTLR4: Lexer.getCharIndex() return value not behaving as expected

I want to extract specific fragment of lexer rule, so I wrote the following rule:
parser grammar TestParser;
options { tokenVocab=TestLexer; }
root
: LINE+ EOF
;
lexer grammar TestLexer;
#lexer::members {
private int startIndex = 0;
private void updateStartIndex() {
startIndex = getCharIndex();
}
private void printNumber() {
String number = _input.getText(Interval.of(startIndex, getCharIndex() - 1));
System.out.println(number);
}
}
LINE: {getCharPositionInLine() == 0}? ANSWER SPACE {updateStartIndex();} NUMBER {printNumber();} .+? NEWLINE;
OTHER: . -> skip;
fragment NUMBER: [0-9]+;
fragment ANSWER: '( ' [A-D] ' )';
fragment SPACE: ' ';
fragment NEWLINE: '\n';
fragment DOT: '.';
Execute the following code:
import org.antlr.v4.runtime.CharStream;
import org.antlr.v4.runtime.CharStreams;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.Lexer;
import org.antlr.v4.runtime.tree.ParseTree;
public class TestParseTest {
public static void main(String[] args) {
CharStream charStream = CharStreams.fromString("( A ) 1. haha\n" +
"( B ) 12. hahaha\n" );
Lexer lexer = new TestLexer(charStream);
CommonTokenStream tokens = new CommonTokenStream(lexer);
TestParser parser = new TestParser(tokens);
ParseTree parseTree = parser.root();
System.out.println(parseTree.toStringTree(parser));
}
}
The output is as follows:
1
12
(root ( A ) 1. haha\n ( B ) 12. hahaha\n <EOF>)
At this point, the value of the fragment NUMBER is printed as expected. Then I add the fragment DOT to the lexer rule LINE:
LINE: {getCharPositionInLine() == 0}? ANSWER SPACE {updateStartIndex();} NUMBER {printNumber();} DOT .+? NEWLINE;
The output of the above test code is as follows:
1
1
(root ( A ) 1. haha\n ( B ) 12. hahaha\n <EOF>)
Why does the second line of output change to 1, this is what I don't understand.
If we modify the test code as follows:
import org.antlr.v4.runtime.CharStream;
import org.antlr.v4.runtime.CharStreams;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.Lexer;
import org.antlr.v4.runtime.tree.ParseTree;
public class TestParseTest {
public static void main(String[] args) {
CharStream charStream = CharStreams.fromString("( B ) 12. hahaha\n"+
"( B ) 123. hahaha\n");
Lexer lexer = new TestLexer(charStream);
CommonTokenStream tokens = new CommonTokenStream(lexer);
TestParser parser = new TestParser(tokens);
ParseTree parseTree = parser.root();
System.out.println(parseTree.toStringTree(parser));
}
}
At this time, when LINE does not contain DOT, the output is as follows:
12
123
(root ( B ) 12. hahaha\n ( B ) 123. hahaha\n <EOF>)
When LINE contains DOT, the output is as follows:
12
12
(root ( B ) 12. hahaha\n ( B ) 123. hahaha\n <EOF>)
Update
I have submitted this issue to GitHub: Lexer.getCharIndex() return value not behaving as expected · Issue #3606 · antlr/antlr4 · GitHub

apex parse csv that contains double quote in every single records

public static List<List<String>> parseCSV(String contents,Boolean skipHeaders) {
List<List<String>> allFields = new List<List<String>>();
// replace instances where a double quote begins a field containing a comma
// in this case you get a double quote followed by a doubled double quote
// do this for beginning and end of a field
contents = contents.replaceAll(',"""',',"DBLQT').replaceall('""",','DBLQT",');
// now replace all remaining double quotes - we do this so that we can reconstruct
// fields with commas inside assuming they begin and end with a double quote
contents = contents.replaceAll('""','DBLQT');
// we are not attempting to handle fields with a newline inside of them
// so, split on newline to get the spreadsheet rows
List<String> lines = new List<String>();
try {
lines = contents.split('\n');
} catch (System.ListException e) {
System.debug('Limits exceeded?' + e.getMessage());
}
Integer num = 0;
for(String line : lines) {
// check for blank CSV lines (only commas)
if (line.replaceAll(',','').trim().length() == 0) break;
List<String> fields = line.split(',');
List<String> cleanFields = new List<String>();
String compositeField;
Boolean makeCompositeField = false;
for(String field : fields) {
if (field.startsWith('"') && field.endsWith('"')) {
cleanFields.add(field.replaceAll('DBLQT','"'));
} else if (field.startsWith('"')) {
makeCompositeField = true;
compositeField = field;
} else if (field.endsWith('"')) {
compositeField += ',' + field;
cleanFields.add(compositeField.replaceAll('DBLQT','"'));
makeCompositeField = false;
} else if (makeCompositeField) {
compositeField += ',' + field;
} else {
cleanFields.add(field.replaceAll('DBLQT','"'));
}
}
allFields.add(cleanFields);
}
if(skipHeaders)allFields.remove(0);
return allFields;
}
I use this part to parse CSV file, but i find out i cant parse when the CSV are all bounded by double quotes.
For example, i have records like these
"a","b","c","d,e,f","g"
After parsing, i would like to get these
a b c d,e,f g
From what I'm seen, the first thing you do is to split the line you get from the CSV file by commas, using this line:
List < String > fields = line.split(',');
When you do this to your own example ("a","b","c","d,e,f","g"), what you get as your list of string is:
fields = ("a" | "b" | "c" | "d | e | f" | "g"), where the bar is used to separate the list elements
The issue here is that, if you first split by commas, it will be a little more difficult to differentiate those commas that are part of a field (because they actually appeared inside quotes), from those that separate fields in you CSV.
I suggest trying do split the line by quotes, which would give you something like this:
fields = (a | , | b | , | c | , | d, e, f | , | g)
and filter out any elements of you list that are only commas and/or spaces, finally achieving this:
fields = (a | b | c | d, e, f | g)
(edited)
Is that Java you're using?
Anyways, here is a Java code that does what you're trying to do:
import java.lang.*;
import java.util.*;
public class HelloWorld
{
public static ArrayList<ArrayList<String>> parseCSV(String contents,Boolean skipHeaders) {
ArrayList<ArrayList<String>> allFields = new ArrayList<ArrayList<String>>();
// separating the file in lines
List<String> lines = new ArrayList<String>();
lines = Arrays.asList(contents.split("\n"));
// ignoring header, if needed
if(skipHeaders) lines.remove(0);
// for each line
for(String line : lines) {
List<String> fields = Arrays.asList(line.split("\""));
ArrayList<String> cleanFields = new ArrayList<String>();
Boolean isComma = false;
for(String field : fields) {
// ignore elements that don't have useful data
// (every other element after splitting by quotes)
isComma = !isComma;
if (isComma) continue;
cleanFields.add(field);
}
allFields.add(cleanFields);
}
return allFields;
}
public static void main(String[] args)
{
// example of input file:
// Line 1: "a","b","c","d,e,f","g"
// Line 2: "a1","b1","c1","d1,e1,f1","g1"
ArrayList<ArrayList<String>> strings = HelloWorld.parseCSV("\"a\",\"b\",\"c\",\"d,e,f\",\"g\"\n\"a1\",\"b1\",\"c1\",\"d1,e1,f1\",\"g1\"",false);
System.out.println("Result:");
for (ArrayList<String> list : strings) {
System.out.println(" New List:");
for (String str : list) {
System.out.println(" - " + str);
}
}
}
}

How do I assign a String at Array1[x] to an int at Array2[x]?

I'm trying to organize data I am given from a text file, there are for 4 pieces of info on each line (City, country, population, and date). I wanted to have an array for each so I first put it all into one big String array and started to separate them into 4 arrays but I needed to change the Population info to an int array but it says *
"Type mismatch: cannot convert from element type int to String"
//Separate the information by commas
while(sc.hasNextLine()){
String line = sc.nextLine();
input = line.split(",");
//Organize the data into 4 seperate arrays
for(int x=0; x<input.length;x++){
if(x%4==0){
cities[x] = input[x];
}
if(x%4==1){
countries[x] = input[x];
}
if(x%4==2){
population[x] = Integer.parseInt(input[x]);
}
if(x%4==3){
dates[x] = input[x];
}
}
}
And when I print out the arrays they have a bunch of nulls in between each data. I'm planning to create objects that have the 4 pieces of data so that I can then sort them by population, dates etc... I'm pretty new to working with objects so if anyone has a better way of getting the 4 pieces of data into an object cause I haven't figured a way yet :/ My end goal was to have an array of these objects that I can u different sorting methods on them
I would recommend doing something like this:
public class MyData {
private String city;
private String country;
private Integer population;
private String date;
public MyData(String city, String, country, Integer population, String date) {
this.city = city;
this.country = country;
this.population = population;
this.date = date;
}
// Add getters and setters here
}
And then in the file you're posting about:
...
ArrayList<MyData> allData = new ArrayList<MyData>();
while(sc.hasNextLine()) {
String[] values = sc.nextLine().split(",");
allData.add(new MyData(values[0], values[1], Integer.parseInt(values[2]), values[3]));
}
...
You need an object to store the data in so that you keep the relationship between the values in each column.
Also, I'm just assuming you're using Java here. Which language we're talking about is something you should include in your question or as a tag.
The problem is with your x index. If you look carefully at your "for" you will see that it will insert a value at every 3 positions.
try
int index = 0;
while(sc.hasNextLine()){
String line = sc.nextLine();
input = line.split(",");
//Organize the data into 4 seperate arrays
for(int x=0; x<input.length;x++){
if(x%4==0){
cities[index] = input[x];
}
if(x%4==1){
countries[index] = input[x];
}
if(x%4==2){
population[index] = Integer.parseInt(input[x]);
}
if(x%4==3){
dates[index] = input[x];
}
}
++index;
}

Square Subsequence

A string is called a square string if it can be obtained by concatenating two copies of the same string. For example, "abab", "aa" are square strings, while "aaa", "abba" are not. Given a string, how many subsequences of the string are square strings? A subsequence of a string can be obtained by deleting zero or more characters from it, and maintaining the relative order of the remaining characters.The subsequence need not be unique.
eg string 'aaa' will have 3 square subsequences
Observation 1: The length of a square string is always even.
Observation 2: Every square subsequence of length 2n (n>1) is a combination of two shorter subsequences: one of length 2(n-1) and one of length 2.
First, find the subsequences of length two, i.e. the characters that occur twice or more in the string. We'll call these pairs. For each subsequence of length 2 (1 pair), remember the position of the first and last character in the sequence.
Now, suppose we have all subsequences of length 2(n-1), and we know for each where in the string the first and second part begins and ends. We can find sequences of length 2n by using observation 2:
Go through all the subsequences of length 2(n-1), and find all pairs where the first item in the pair lies between the last position of the first part and the first position of the second part, and the second item lies after the last position of the second part. Every time such a pair is found, combine it with the current subsequence of length 2(n-2) into a new subsequence of length 2n.
Repeat the last step until no more new square subsequences are found.
Psuedocode:
total_square_substrings <- 0
# Find every substring
for i in 1:length_of_string {
# Odd strings are not square, continue
if((length_of_string-i) % 2 == 1)
continue;
for j in 1:length_of_string {
# Remove i characters from the string, starting at character j
substring <- substr(string,0,j) + substr(string,j+1,length_of_string);
# Test all ways of splitting the substring into even, whole parts (e.g. if string is of length 15, this splits by 3 and 5)
SubstringTest: for(k in 2:(length_of_substring/2))
{
if(length_of_substring % k > 0)
continue;
first_partition <- substring[1:partition_size];
# Test every partition against the first for equality, if all pass, we have a square substring
for(m in 2:k)
{
if(first_partition != substring[(k-1)*partition_size:k*partition_size])
continue SubstringTest;
}
# We have a square substring, move on to next substring
total_square_substrings++;
break SubstringTest;
}
}
}
Here's a solution using LINQ:
IEnumerable<string> input = new[] {"a","a","a"};
// The next line assumes the existence of a "PowerSet" method for IEnumerable<T>.
// I'll provide my implementation of the method later.
IEnumerable<IEnumerable<string>> powerSet = input.PowerSet();
// Once you have the power set of all subsequences, select only those that are "square".
IEnumerable<IEnumerable<string>> squares = powerSet.Where(x => x.Take(x.Count()/2).SequenceEqual(x.Skip(x.Count()/2)));
Console.WriteLine(squares);
And here is my PowerSet extension method, along with a "Choose" extension method that is required by PowerSet:
public static class CombinatorialExtensionMethods
{
public static IEnumerable<IEnumerable<T>> Choose<T>(this IEnumerable<T> seq, int k)
{
// Use "Select With Index" to create IEnumerable<anonymous type containing sequence values with indexes>
var indexedSeq = seq.Select((Value, Index) => new {Value, Index});
// Create k copies of the sequence to join
var sequences = Enumerable.Repeat(indexedSeq,k);
// Create IEnumerable<TypeOf(indexedSeq)> containing one empty sequence
/// To create an empty sequence of the same anonymous type as indexedSeq, allow the compiler to infer the type from a query expression
var emptySequence =
from item in indexedSeq
where false
select item;
var emptyProduct = Enumerable.Repeat(emptySequence,1);
// Select "Choose" permutations, using Index to order the items
var indexChoose = sequences.Aggregate(
emptyProduct,
(accumulator, sequence) =>
from accseq in accumulator
from item in sequence
where accseq.All(accitem => accitem.Index < item.Index)
select accseq.Concat(new[] { item }));
// Select just the Value from each permutation
IEnumerable<IEnumerable<T>> result =
from item in indexChoose
select item.Select((x) => x.Value);
return result;
}
public static IEnumerable<IEnumerable<T>> PowerSet<T>(this IEnumerable<T> seq)
{
IEnumerable<IEnumerable<T>> result = new[] { Enumerable.Empty<T>() };
for (int i=1; i<=seq.Count(); i++)
{
result = result.Concat(seq.Choose<T>(i));
}
return result;
}
}
I initially derive all possible sub-sequences and then i will check if the derived sub-sequence is a square sub-sequence or not
import java.io.*;
import java.util.*;
public class Subsequence {
static int count;
public static void print(String prefix, String remaining, int k) {
if (k == 0) {
//System.out.println(prefix);
if(prefix.length() %2 == 0 && check(prefix) != 0 && prefix.length() != 0)
{
count++;
//System.out.println(prefix);
}
return;
}
if (remaining.length() == 0)
return;
print(prefix + remaining.charAt(0), remaining.substring(1), k-1);
print(prefix, remaining.substring(1), k);
}
public static void main(String[] args)
{
//String s = "aaa";
Scanner sc = new Scanner(System.in);
int t=Integer.parseInt(sc.nextLine());
while((t--)>0)
{
count = 0;
String s = sc.nextLine();
for(int i=0;i<=s.length();i++)
{
print("",s,i);
}
System.out.println(count);
}
}
public static int check(String s)
{
int i=0,j=(s.length())/2;
for(;i<(s.length())/2 && j < (s.length());i++,j++)
{
if(s.charAt(i)==s.charAt(j))
{
continue;
}
else
return 0;
}
return 1;
}
}
import java.io.*;
import java.util.*;
public class Solution {
/*
Sample Input:
3
aaa
abab
baaba
Sample Output:
3
3
6
*/
public static void main(String[] args) {
//Creating an object of SquareString class
SquareString squareStringObject=new SquareString();
Scanner in = new Scanner(System.in);
//Number of Test Cases
int T = in.nextInt();
in.nextLine();
String[] inputString=new String[T];
for(int i=0;i<T;i++){
// Taking input and storing in String Array
inputString[i]=in.nextLine();
}
for(int i=0;i<T;i++){
//Calculating and printing the number of Square Strings
squareStringObject.numberOfSquareStrings(inputString[i]);
}
}
}
class SquareString{
//The counter maintained for keeping a count of Square Strings
private int squareStringCounter;
//Default Constructor initialising the counter as 0
public SquareString(){
squareStringCounter=0;
}
//Function calculates and prints the number of square strings
public void numberOfSquareStrings(String inputString){
squareStringCounter=0;
//Initialising the string part1 as a single character iterated over the length
for(int iterStr1=0;iterStr1<inputString.length()-1;iterStr1++){
String str1=""+inputString.charAt(iterStr1);
String str2=inputString.substring(iterStr1+1);
//Calling a recursive method to generate substring
generateSubstringAndCountSquareStrings(str1,str2);
}
System.out.println(squareStringCounter);
}
//Recursive method to generate sub strings
private void generateSubstringAndCountSquareStrings(String str1,String str2){
for(int iterStr2=0;iterStr2<str2.length();iterStr2++){
String newStr1=str1+str2.charAt(iterStr2);
if(isSquareString(newStr1)){
squareStringCounter++;
}
String newStr2=str2.substring(iterStr2+1);
generateSubstringAndCountSquareStrings(newStr1,newStr2);
}
}
private boolean isSquareString(String str){
if(str.length()%2!=0)
return false;
String strPart1=str.substring(0,str.length()/2);
String strPart2=str.substring(str.length()/2);
return strPart1.equals(strPart2);
}
}

How to draw rectangular in J2ME by canvas through drawline method

This is first time I at a question in here.
Im new in J2ME, and now im developing a small application, but i get problem when i wanna show data into table. But in J2me not support table there for that i know another way can represent for table such as create table by Canvas or CustomItem.
In Canvas i can draw 2 lines something like:
-----------------------
|
|
|
|
but i dont know how can get coordinate of 2 lines remain such as like:
|
|
|
|
|
--------------------------
two draw a rectangular in whole screen,
i know drawline method has 4 factors x1,y1,x2,y2.
but i can not calculate x point and y point to draw two lines above
I need you help me explain or give me example
My Code:
package test;
import javax.microedition.lcdui.Canvas;
import javax.microedition.lcdui.Graphics;
/**
*
* #author J2MENewBie
*/
public class TableCanvasExample extends Canvas {
private int cols=3;
private int rows =50;
protected void paint(Graphics g) {
g.setColor(0x94b2ff);
g.fillRect(0, 0, this.getWidth(), this.getHeight());
//draw two lines
g.setColor(0xf8011e);
g.drawLine(0, 0, 0, this.getWidth());
g.drawLine(0, 0, this.getHeight(), 0);
}
}
package test;
import javax.microedition.lcdui.Display;
import javax.microedition.midlet.*;
/**
* #author J2ME NewBie
*/
public class TableCanvasMidlet extends MIDlet {
private TableCanvasExample tbcve;
public TableCanvasMidlet(){
tbcve = new TableCanvasExample();
}
public void startApp() {
Display.getDisplay(this).setCurrent(tbcve);
}
public void pauseApp() {
}
public void destroyApp(boolean unconditional) {
}
}
P/s: the vertical line doesn't full size i dont know why ???
Thank you!
too much same-looking zeroes in your code - try using descriptive names instead:
int w = getWidth(), h = getHeight(); // I think this way it's easier to read
int xLeft = 0, yTop = 0; // descriptive names for zeroes
// below, replace w - 1 -> w and h - 1 -> h if lines drawn are off-by-one
int xRight = w - 1, yBottom = h - 1; // names for top - right coordinates
g.drawLine(xLeft, yTop, xLeft, yBottom); // your left vertical
g.drawLine(xLeft, yTop, xRight, yTop); // your top horizontal
g.drawLine(xRight, yTop, xRight, yBottom); // add right vertical
g.drawLine(xLeft, yBottom, xRight, yBottom); // add bottom horizontal
if rectangle drawn doesn't look like you expect find where there is wrong semantic in code above

Resources