In my program, I am reading data from a CSV file which follows the pattern of dance group and then the dancers in the group. I am struggling to sort the dancers names alphabetically.
public String listAllDancesAndPerformers() {
// get CSV file for dances Data
ArrayList<String> dancesData = getCSV("src/csvFiles/danceShowData_dances.csv");
int lineNumber = 0;
String result = "";
//for each line in dances csv file
for (String line : dancesData) {
//split into two sections - [0] is name of dance & [1] is dancers
String[] splitByTab = line.split("\t");
//take the dancers [1] of splitByTab and split it by commas
// this makes that seperatedNames[1], [2] etc are all the dancers
//and i am supposed to sort the seperated names to print out alphabetticaly
String[] separatedNames = splitByComma(splitByTab[1]);
lineNumber++;
result += lineNumber + ": ";
result += (splitByTab[0].trim()) + "\n";
result += (listAllDancersIn(splitByTab[0].trim())) + "\n";
}
return result;
}
list all dancers method which takes an input of a dance name and then prints out the dance name followed by the dancers inside reading from the CSV file
public String listAllDancersIn(String dance) {
// get CSV file for dances Data
ArrayList<String> dancesData = getCSV("src/csvFiles/danceShowData_dances.csv");
String result = "";
// for each line in dances csv file
for (String line : dancesData) {
// split into two sections - [0] is name of dance & [1] is dancers
String[] splitByTab = line.split("\t");
splitByTab[0] = splitByTab[0].trim();
// if name of dance matches given dance name
if (splitByTab[0].equals(dance)) {
// split names of dancers into individual strings
String[] separatedNames = splitByComma(splitByTab[1]);
// iterate through names
for (int i = 0; i < separatedNames.length; i++) {
// append result with output of getDanceGroupMembers (and trim input)
result += ", " + getDanceGroupMembers(separatedNames[i].trim());
}
}
}
// remove leading comma and space
result = result.substring(2);
return result;
}
In your listAllDancersIn method, use an ArrayList instead of your result += instructions.
Then at end, you can use the default sorter, which will sort alphabetically:
Collections.sort(resultAsList);
ANd if you still want this method to return a sorted string, instead of a sorted list, you can do it this way, using Join method:
return String.join(", ", resultAsList);
Marius, see whether below code works as you intended.
import java.util.ArrayList;
import java.util.Collections;
public class SortDancers {
public static void main(String[] args) {
System.out.println(new SortDancers().listAllDancesAndPerformers());
}
public String listAllDancesAndPerformers() {
ArrayList<String> dancesData = new ArrayList<String>();
dancesData.add("Dance1 \t Kelly, Andrew, Nathan");
dancesData.add("Dance2 \t John, Sally, Kevin, Abby");
dancesData.add("Dance3 \t Laura, Benny, Jane");
// I assume you get this kind of data from getCSV()
int lineNumber = 0;
String result = "";
for (String line : dancesData) {
String[] splitByTab = line.split("\t");
String[] separatedNames = splitByTab[1].split(",");
lineNumber++;
result += lineNumber + ": ";
result += (splitByTab[0].trim()) + "\n";
ArrayList<String> separatedNamesList = new ArrayList<String>();
for (int i = 0; i < separatedNames.length; i++) {
separatedNamesList.add(separatedNames[i].trim());
}
Collections.sort(separatedNamesList);
result += String.join(", ", separatedNamesList);
result += "\n";
}
return result;
}
}
I think you should split your code:
Read CSV file and build correct data structure;
Print data structure to console or String.
public static Map<String, Set<String>> listAllDancesAndPerformers() {
final Pattern pattern = Pattern.compile("(?<group>\\w+)\\t+(?<dancers>.+)");
final Pattern comma = Pattern.compile("\\s*,\\s*");
Map<String, Set<String>> groups = new TreeMap<>();
for (String line : getCSV("src/csvFiles/danceShowData_dances.csv")) {
Matcher matcher = pattern.matcher(line);
if (matcher.matches())
groups.put(matcher.group("group"), new TreeSet<>(Arrays.asList(comma.split(matcher.group("dancers")))));
}
return groups;
}
If danceShowData_dances.csv file content is:
beginners anna,maria,olga
mature bob,marvin,peter
Then result Map will contain:
"beginners" : ["anna", "maria", "olga"]
"mature" : ["bob", "marvin", "peter"]
And finally you can create method that convert given Map into String with required format:
public static String printToString(Map<String, Set<String>> groups) {
int count = 1;
StringBuilder buf = new StringBuilder();
for (Map.Entry<String, Set<String>> entry : groups.entrySet()) {
if (buf.length() > 0)
buf.append('\n');
buf.append(count++).append(':');
buf.append(entry.getKey());
if (!entry.getValue().isEmpty())
buf.append('\n').append(String.join(", ", entry.getValue()));
}
return buf.toString();
}
Output:
1:beginners
anna, maria, olga
2:mature
bob, marvin, peter
Related
I have a string as:
"model=iPhone12,3,os_version=13.6.1,os_update_exist=1,status=1"
How can I convert this into:
model=iPhone12,3
os_version=13.6.1
os_update_exist=1
status=1
Split the string from the first comma, then re-join the first two elements of the resulting string array.
I doubt there's a "clean" way to do this but this would work for your case:
String str = "model=iPhone12,3,os_version=13.6.1,os_update_exist=1,status=1";
String[] sp = str.split(",");
sp[0] += "," + sp[1];
sp[1] = sp[2];
sp[2] = sp[3];
sp[3] = sp[4];
sp[4] = "";
You can try this:
public String[] splitString(String source) {
// Split the source string based on a comma followed by letters and numbers.
// Basically "model=iPhone12,3,os_version=13.6.1,os_update_exist=1,status=1" will be split
// like this:
// model=iPhone12,3
// ,os_version=13.6.1
// ,os_update_exist=1
// ,status=1"
String[] result = source.split("(?=,[a-z]+\\d*)");
for (int i = 0; i < result.length; i++) {
// Removes the comma at the beginning of the string if present
if (result[i].matches(",.*")) {
result[i] = result[i].substring(1);
}
}
return result;
}
if you are parsing always the same kind of String a regex like this will be do the job
String str = "model=iPhone12,3,os_version=13.6.1,os_update_exist=1,status=1";
Matcher m = Pattern.compile("model=(.*),os_version=(.*),os_update_exist=(.*),status=(.*)").matcher(str);
if (m.find()) {
model = m.group(1)); // iPhone12,3
os = m.group(2)); // 13.6.1
update = m.group(3)); // 1
status = m.group(4)); // 1
}
If you really wants to use a split you can still use that kind of trick
String[] split = str.replaceAll(".*?=(.*?)(,[a-z]|$)", "$1#")
.split("#");
split[0] // iPhone12,3
split[1] // 13.6.1
split[2] // 1
split[3] // 1
How Would we write a program using Java to read a paragraph from the user and replace specific words mentioned in a vector to the following format, i.e.,
For example word Happy is reduced to H****.
Any Help will be Appriciated.
import java.io.*;
import java.util.*;
class replaceString {
public static String putStars(String str) {
char first_char = str.charAt(0);
String ans = new String();
ans = String.valueOf(first_char);
for(int i = 1;i < str.length(); ++i ) {
ans = ans + "*";
}
return ans;
}
public static String replaceWords(String str, Vector<String> v1) {
String[] words = str.split("\\W+"); //split across all types of punctuation
String ansString = new String();
for(String to_be_replaced : words) {
boolean found = false;
for(String to_replace_with : v1) {
if(to_be_replaced.equals(to_replace_with)) {
//System.out.println("in");
ansString = ansString +putStars(to_be_replaced) + " ";
found = true;
}
}
if(found == false) {
ansString = ansString + to_be_replaced + " ";
}
}
return ansString;
}
public static String replaceWords1(String str, Vector<String> v1) {
for(String currStr : v1) {
str.replace(str, );
}
return ansString;
}
public static void main(String args[])throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.out.println("Enter the paragraph that you would like to edit ");
String s = br.readLine();
// Let us assume some strings in our very own vector
Vector<String> v1 = new Vector<String>();
v1.addElement("Hello");
v1.addElement("Hi");
v1.addElement("Heya");
v1.addElement("Howdy");
v1.addElement("Howu");
String ans = replaceWords(s, v1);
System.out.println("Paragraph after replacement becomes\n\n"+ ans);
}
}
this is my current code but its not working fine
There could be other possibilities, but here's an example I did based on this answer:
We need all the words we need / want to match, and store them in an array:
String [] words = {"appy", "eya", "dy"};
(Optional) If you really need a Vector, I suggest to create a List (ArrayList) instead, and we can do it this way:
List <String> wordsToReplace = Arrays.asList(words);
Otherwise just modify the method in the next step to receive an array...
We create a function that receives this List and the phrase we want to check for and that returns the new String with the replaced text in it
So, our whole code ends up like this:
import java.util.Arrays;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class WordReplacer {
public static void main(String[] args) {
String [] words = {"appy", "eya", "dy"};
List <String> wordsToReplace = Arrays.asList(words);
System.out.println(replaceWords("Happy", wordsToReplace));
System.out.println(replaceWords("Heya", wordsToReplace));
System.out.println(replaceWords("Howdy?", wordsToReplace));
System.out.println(replaceWords("Howdy? My friend lives in Pompeya and every time I see her I say \"Heya\" to her, she is very happy", wordsToReplace));
}
private static String replaceWords(String word, List <String> wordsToReplace) {
for (String s : wordsToReplace) {
Pattern p = Pattern.compile(s, Pattern.CASE_INSENSITIVE); //We create a pattern that matches each word in our list. (1)
Matcher m = p.matcher(word); //We actually check for each match against our phrase
StringBuilder sb = new StringBuilder();
if (m.find()) { //If there was a match, we're going to replace each character for an '*' (2)
for (int i = 0; i < s.length(); i++) {
sb.append("*");
}
}
word = m.replaceAll(sb.toString()); //We replace each match with '*' (3)
}
return word; //We return the modified word
}
}
I'm going to explain what each comment (1), (2), (3) do in a better and simpler way:
(1) As shown in the linked answer, they use \b regex command to match whole words, but in this case we're using it to match parts of words, not whole words, so we don't need it here...
(2) Only if we found a match we fill the StringBuilder with * characters... If we didn't do it this way, we would be getting: H* instead of H**** for the case of Happy word, this way we ensure we get the correct amount of * for every word in the List.
(3) We replace the matches for the total number of * in the StringBuilder so we get the correct output.
The program above produces the following output:
H****
H***
How**?
How**? My friend lives in Pomp*** and every time I see her I say "H***" to her, she is very h****
Try something like that with a map that contains yours replacing rules :
String input; //input string
Map<String,String> mapReplace = new HashMap<String,String>();
mapReplace.put("Hello","H****");
Iterator<String> keys = mapReplace.keySet().iterator();
while(keys.hasNext()){
String key = keys.next();
input = input.replace(input, mapReplace.get(key));
}
i have a large string which contains Id's example :
HD47-4585-GG89
here at the above i have an id of a single object but sometimes it may contain id's of multiple objects like this :
HD47-4585-GG89-KO89-9089-RT45
the above haves ids of 2 objects now i want to convert the above string to an array or in multiple small Strings
something like :
id1 = HD47-4585-GG89
id2 = KO89-9089-RT45
every single id haves a fixed number of characters in it here its 14 (counting the symbols too) and the number of total id's in a single String is not determined
i dont know how to do it any one can guide me with this ?
i think all i have to do is clip the first 14 characters of string then assign a variable to it and repeat this until string is empty
You could also use regex:
String input = "HD47-4585-GG89-KO89-9089-RT45";
Pattern id = Pattern.compile("(\\w{4}-\\w{4}-\\w{4})");
Matcher matcher = id.matcher(input);
List<String> ids = new ArrayList<>();
while(matcher.find()) {
ids.add(matcher.group(1));
}
System.out.println(ids); // [HD47-4585-GG89, KO89-9089-RT45]
See Ideone.
Although this assumes that each group of characters (HD47) is 4 long.
Using guava Splitter
class SplitIt
{
public static void main (String[] args) throws java.lang.Exception
{
String idString = "HD47-4585-GG89-KO89-9089-RT45-HD47-4585-GG89";
Iterable<String> result = Splitter
.fixedLength(15)
.trimResults(CharMatcher.inRange('-', '-'))
.split(idString);
String[] parts = Iterables.toArray(result, String.class);
for (String id : parts) {
System.out.println(id);
}
}
}
StringTokenizer st = new StringTokenizer(String,"-");
while (st.hasMoreTokens()) {
System.out.println(st.nextToken());
}
these tokens can be stored in some arrays and then using index you can get required data.
String text = "HD47-4585-GG89-KO89-9089-RT45";
String first = "";
String second = "";
List<String> textList = Arrays.asList(text.split("-"));
for (int i = 0; i < textList.size() / 2; i++) {
first += textList.get(i) + "-";
}
for (int i = textList.size() / 2; i < textList.size(); i++) {
second += textList.get(i) + "-";
}
first = first.substring(0, first.length() - 1);
second = second.substring(0, second.length() - 1);
I am trying to create a program that counts the number of times a word appears in a text and also tell you how many times it appears on each line. I have managed to find the number of times the word appears and the number of lines in the text, but I cannot find on which line the word appears in and how many times. Could you please help me? This is my code so far:
FileReader file = new FileReader("C:/Users/User/Desktop/test.txt");
BufferedReader buffer = new BufferedReader(file);
String line = buffer.readLine();
Map<String, Integer> hash = new HashMap<String, Integer>();
int counter = 0; //number of lines
while (line != null){
String[] words = line.split(" ");
for (String s : words) {
Integer i = hash.get(s);
hash.put(s, (i==null)? 1: i+1);
}
line = buffer.readLine();
counter = counter + 1;
}
System.out.println(hash);
System.out.println(counter);
It is additional information to each row. You just need an information of count on each line, therefore simple Map is not enough, you need Map of Map at each row.
There are two basic ways :
Map<Integer, Map<String, Integer>> hashOfHash = new HashMap<>();
List<Map<String, Integer>> list = new ArrayList<>();
First line creates Map of your Map based on integer key value - which would be the line.
Second line is creating list of your Maps, because the order in list is stored, you can now which line is which just by iterating through it.
I would recommend second line.
You need also modify your while cycle a bit to be able to create new map for each line (think about it that you need to do the same as it does at first line).
For example this should do the same as your program, but it will show results for each row :
public static void main(String[] args) throws FileNotFoundException, IOException {
FileReader file = new FileReader("C:/Users/User/Desktop/test.txt");
BufferedReader buffer = new BufferedReader(file);
String line = buffer.readLine();
List<Map<String, Integer>> list = new ArrayList<>();
while (line != null) {
Map<String, Integer> hash = new HashMap<String, Integer>();
String[] words = line.split(" ");
for (String s : words) {
Integer i = hash.get(s);
hash.put(s, (i == null) ? 1 : i + 1);
}
line = buffer.readLine();
list.add(hash);
}
int i=0;
for (Map<String, Integer> mapAtRow : list) {
i++;
System.out.println("at row " + i + "we found this: " + mapAtRow);
}
}
Here is a recursive method that will allow you, using String.indexOf to count how many times a word appears in a line.
You have read the line from your bufferedReader
String line = buffer.readLine();
then in your loop you have
for (String s : words) {
int numberOfOccurencesOfS = countNumberOfTimesInALine(line,s);
}
the countNumberOfTimesInALinereceives the original line and the word your are counting as arguments. To use it you should also declare a class variable like this:
private static int numberOfLineOccurences;
Here is the method
public static int countNumberOfTimesInALine(String line, String word) {
if (line.indexOf(word) == -1) {
return numberOfLineOccurences;
} else {
numberOfLineOccurences++;
if (line.indexOf(word) + word.length() > line.length() -1 ) {
return numberOfLineOccurences;
}
return countNumberOfTimesInALine(
line.substring(line.indexOf(word) + word.length()), word );
}
}
Here is a usage example:
String line = "DEMO TEST DEMO TEST DEMO TEST ALPHA BETA GAMMA";
System.out.println("Number of occurences of TEST is " + countNumberOfTimesInALine(line, "TEST"));
Here is the result
Number of occurences of TEST is 3
I have published an answer to a similar question as yours here
I am doing an android app, where i read the text from an image and i get an output string like below,
NAME : michael /nPHONE NO: 771234521/n e-Mail: michael#gmai|.com /nCompany:
Google/n
I want to extract them individually as a string, and assign to a variable like,
String Name = "michael";
String Phone = "771234521";
how can i achieve like this,here is my piece of code,
input.setText(recognizedText);
String[] separated = recognizedText.split("/");
for (String s: separated)
{
}
I think want to parse your fields into a Map, and that they are separated on the newline character (\n). Perhaps like this -
// Convert the string in to a Map<String, String>.
public static Map<String, String> toMap(String in) {
// the return map.
Map<String, String> map = new HashMap<String, String>();
// a tokenizer on newline
StringTokenizer st = new StringTokenizer(in, "\n");
while (st.hasMoreTokens()) { // while there are lines.
String token = st.nextToken(); // get the line.
String[] kv = token.split(":"); // split on colon.
if (kv.length > 1) { // check that there's a key and a
// value.
map.put(kv[0].trim(), kv[1].trim()); // add it to
// the map.
}
}
return map; // return the map.
}
public static void main(String[] args) {
String str = "NAME : michael \nPHONE NO: 771234521\n"
+ " e-Mail: michael#gmai|.com \nCompany: Google\n";
Map<String, String> map = toMap(str);
System.out.println(map);
}
Which outputs this here -
{NAME=michael, e-Mail=michael#gmai|.com, Company=Google, PHONE NO=771234521}
public static void main(String... args) {
String s = "NAME : michael /nPHONE NO: 771234521/n e-Mail: michael#gmai|.com /nCompany: Google/n";
String[] str = s.split("/n");
for(int i=0;i<str.length;i++)
{
str[i]=str[i].trim();
}
for (int k = 0; k < 4; k++) {
System.out.println(str[k]);
}
}
O/P :
NAME : michael
PHONE NO: 771234521
e-Mail: michael#gmai|.com
Company: Google
You should use String Tokenizer like this
Tokenize the string based on your delimeter /
String src = "NAME : michael /nPHONE NO: 771234521/n e-Mail: michael#gmai|.com /nCompany: Google/n";
String noLineSrc = src.replace("/n", ",");
String[] couples = noLineSrc.split(",");
Map<String, String> result = new HashMap<String, String>();
for(String couple : couples) {
String[] coupleValue = couple.split(":");
result.put(coupleValue[0].trim(), coupleValue[1].trim());
}
The keys are: "NAME:", "PHONE NO:", "e-Mail:", and "Company:".
After splitting the string with split("/n"), you can do a str[i].contains("Name:") to check for the key.
The value comes after the ":". So, int pos = str[i].indexof(":") + 1 will be the starting position of the value.
String value = str[i].substring(pos) gives you the value.
Then value.trim() to remove spaces.