split ArrayList String - java

how do I split arrayList String
SCHOOLWORK
BALCONY
INSIST
SALTPETER
BOLTON
KITSCHY
CLIENTELE
I want to split those words to "SCH", "OOL", "WO", "RK".
Here is my code
import java.io.File;
import java.util.ArrayList;
public class HW2 {
public static ArrayList<String> getTiles(ArrayList<String> input_list_of_strings) {
// create a substring by go through the loop first, then .... (instruction)
Object[] subString = new Object[input_list_of_strings.size()];
for (int i = 0; i < input_list_of_strings.size(); i++) {
subString[i] = input_list_of_strings.get(i);
// test just want to see if subString get all String
// System.out.println(subString[i]);
String delim=" ";
String[] splitstrings = ((String) subString[i]).split(delim);
for (int j = 0; j < splitstrings.length; j++) {
splitstrings[j] +=delim;
System.out.println(splitstrings[j]);
}
}
return input_list_of_strings;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
ArrayList<String> input_words = new ArrayList<String>();
input_words.add("SCHOOLWORK");
input_words.add("BALCONY");
input_words.add("INSIST");
input_words.add("SALTPETER");
input_words.add("BOLTON");
input_words.add("KITSCHY");
input_words.add("CLIENTELE");
System.out.print(getTiles(input_words));
}
}
Thank you...

I would use an interface to encapsulate how you want to split each string.
public static interface StringSplitter {
public List<String> splitString(String s);
}
Then your 'getTiles' method would simply be:
public static ArrayList<String> getTiles(ArrayList<String> input,StringSplitter splitter) {
int initSize = input.size();
for(int i = 0; i < initSize; i++) {
String source = input.remove(0); //Remove from head
input.addAll(splitter.splitString(source)); //Add to end
}
return input;
}
NOTE: This method modifies the original list, it can be easily adapted to simply copy the list if need be. Although, I like it better this way.
Since the exact process for splitting these words is unclear, I am going to guess that you want to keep splitting a word by three characters, unless that would leave only one character, then split by two - else don't split. So your default 'StringSplitter' would be:
public static final StringSplitter DEFAULT_SPLITTER = new StringSplitter() {
#Override
public List<String> splitString(String s) {
List<String> subs = new ArrayList();
while(!s.isEmpty()){
int splitsize = 0;
if(s.length() < 5) {
if(s.length() == 4) {
splitsize = 2;
} else {
splitsize = s.length();
}
} else {
splitsize = 3;
}
subs.add(s.substring(0,splitsize));
s = s.substring(splitsize);
}
return subs;
}
};
Your main method would then be:
public static void main(String[] args) {
// TODO Auto-generated method stub
ArrayList<String> input_words = new ArrayList<String>();
input_words.add("SCHOOLWORK");
input_words.add("BALCONY");
input_words.add("INSIST");
input_words.add("SALTPETER");
input_words.add("BOLTON");
input_words.add("KITSCHY");
input_words.add("CLIENTELE");
System.out.print(getTiles(input_words),DEFAULT_SPLITTER); //Make sure to use DEFAULT_SPLITTER
}

First iterate through your ArrayList<String>. For each word in the ArrayList, split it into chunks. Your example above doesn't make much sense -- why is "SCHOOLWORK" split into "SCH", "OOL", "WO", "RK" and not "SCHOOL" and "WORK" ? Without understanding the logic behind your requirements, all we can give are general suggestions.
So, basically:
// iterate through the arraylist
ArrayList<String> allWords; // instantiate this
...
for(String word : allWords) {
splitWord(word);
}
And create a method splitWord(String) that applies whatever logic you need aginst the word to split it up. I suggest looking into String's substring() method if you need words of a certain size.

Related

Filtering out Repeated Characters in Java

I am trying to write a program that has the method public static void method(List<String> words) where the parameter words is a list of words from the text file words.txt that are sorted and contain only the words where each letter occurs only once. For example, the word "feel" would not be included in this list since "e" occurs more than once. The word list is not to be used as an argument in the rest of the program, so the method method is only to be used to store and remember the wordlist for later use. This function can also perform any of the sorting methods.
My thought process was to create a method that would read the text file, and use that text file as the argument in method. method would then filter out all words with letters that appear more than once, and also sort the new list.
When running the program, I'm getting an error "java.util.ConcurrentModificationException: null (in java.util.LinkedList$Listltr)" on the line for (String word : words). Also does the line public static List list; properly save and store the list for later use?
import java.util.*;
import java.io.*;
class ABC
{
public static List<String> list = new LinkedList<String>()
public static List readFile()
{
String content = new String();
File file = new File("words.txt");
LinkedList<String> words = new LinkedList<String>();
try
{
Scanner sc = new Scanner(new FileInputStream(file));
while (sc.hasNextLine())
{
content = sc.nextLine();
words.add(content);
}
}
catch (FileNotFoundException fnf)
{
fnf.printStackTrace();
}
catch (Exception e)
{
e.printStackTrace();
System.out.println("\nProgram terminated safely");
}
for (String word : words)
{
if (letters(word) == false)
{
list.add(word);
}
}
Collections.sort(list);
return list;
}
public static boolean letters(String word)
{
for (int i = 0; i < word.length() - 1; i++)
{
if (word.contains(String.valueOf(word.charAt(i))) == true)
{
return true;
}
}
return false;
}
public static void main(String args[])
{
System.out.println(readFile());
}
}
The source of the error is that you are changing a list that you are iterating on. This is generally not a good idea.
Since you are building a new list, you don't actually need to change the one you are iterating on. I would recommend changing your code so that the logic for deciding if a letter appears more than once goes in a separate method. This way the complexity of any given method is manageable, and you can test them separately.
So create a new method that tests if any letter appears more than once:
static boolean doesAnyLetterAppearMoreThanOnce(String word) {
...
}
Then you can use it in your existing method:
for (String word : words) {
if (!doesAnyLetterAppearMoreThanOnce(word)) {
list.add(word);
}
}
Collections.sort(list);
Use an iterator. Try it like this.
Iterator<String> it = words.iterator();
while(it.hasNext()) {
CharSequence ch = it.next();
for (int j = 0; j < ch.length(); j++)
{
for (int k = j + 1; k < ch.length(); k++)
{
if (ch.charAt(j) == ch.charAt(k))
{
it.remove(word);
}
}
}
list.add(word);
}
However, I would approach it differently.
String[] data =
{ "hello", "bad", "bye", "computer", "feel", "glee" };
outer: for (String word : data) {
for (int i = 0; i < word.length() - 1; i++) {
if (word.charAt(i) == word.charAt(i + 1)) {
System.out.println("dropping '" + word + "'");
continue outer;
}
}
System.out.println("Keeping '" + word + "'");
List.add(word);
}
Note: You used feel as an example so it wasn't clear if you wanted to check for the same letter anywhere in the word or only adjacent letters that are the same.
There are several problems with you program:
public static List list;
Whenever you see a collection (like List) without a generics - it's a bad smell. Should be public static List<String> list;
Also consider changing public to private.
In readFile() method you mask the class variable 'list' with a local variable 'list'. So your class variable remains uninitialized:
list = new LinkedList<String>();
Better use try-with-resources for scanner:
try(Scanner sc = new Scanner(new FileInputStream(file))) {
You don't need to close it afterwards manually.
You cannot modify the list through which you are iterating. You should either use an iterator and its remove method, or create a new list and append good words to it, instead of removing bad words from the original list.
public static List<String> readFile() {
File file = new File("words.txt");
List<String> list = new ArrayList<>();
try (Scanner scanner = new Scanner(file)) {
while (scanner.hasNextLine()) {
String word = scanner.nextLine();
if (noDuplicates(word)) {
list.add(word);
}
}
Collections.sort(list);
} catch (FileNotFoundException e) {
System.out.println("File not found");
}
return list;
}
private static boolean noDuplicates(String word) {
Set<Character> distinctChars = new HashSet<>();
for (char c : word.toCharArray()) {
if (!distinctChars.add(c)) {
return false;
}
}
return true;
}
I suggest this shorter approach:
public static void method(List<String> words) {
words.removeIf(word -> {
Set<Integer> hs = new HashSet<>();
return word.chars().anyMatch(c -> {
if (hs.contains(c)) return true;
else hs.add(c);
return false;
});
});
System.out.println(words);}
words List now contain only the words where each letter occurs only once.

How can i split up an ArrayList of strings between letters and numbers WITHOUT using the split method?

To take an arraylist of strings consisting of strings like:
fewf5677
kskfj654
pqoen444
mgnwo888
And i want to split them up BUT i DON'T want to use the split method because I have to perform other calculations with the letters that i'have split up.
SO i'have decided to use the subList method. But I can't seem to find a proper example of implementing this correctly. Take a look at my code. Below is a method that takes in an arraylist of strings as the parameter:
public static void splitup(ArrayList<String> mystrings){
mystrings.subList(String[] letters, double numbers);
}
So overall, how do I take each string of letters and numbers and store them into their own string arrays? For example, i want
fewf
kskfj
pqoen
mgnwo
to be in their own string along with
5677
654
444
888
to be their own numbers.
You could use regex as seen in this answer and then check for a pattern as shown in this answer as follows:
import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class StringSplitter {
public static void main(String[] args) {
ArrayList<String> myStringsList = new ArrayList<String>();
ArrayList<String> stringsList = new ArrayList<String>();
ArrayList<String> numbersList = new ArrayList<String>();
myStringsList.add("fewf5677");
myStringsList.add("kskfj654");
myStringsList.add("pqoen444");
myStringsList.add("mgnwo888");
for (String s : myStringsList) {
String splittedString[] = s.split("(?<=\\D)(?=\\d)|(?<=\\d)(?=\\D)");
for (String string : splittedString) {
Matcher match = Pattern.compile("[0-9]").matcher(string);
if (match.find()) {
numbersList.add(string);
} else {
stringsList.add(string);
}
}
}
for (String s : numbersList) {
System.out.println(s);
}
for (String s : stringsList) {
System.out.println(s);
}
}
}
This will output:
5677
654
444
888
fewf
kskfj
pqoen
mgnwo
Remember that split() takes a regex as parameter, not a String and so, you can do something like the above code to get the desired output.
What you are trying to do is a bit strange. Why are you trying to overload subList method?
One of possible examples of what you could do is to iterate over mystrings list and separate each string into two variables.
http://crunchify.com/how-to-iterate-through-java-list-4-way-to-iterate-through-loop/
If you are familiar with regular expressions you can use them them.
If not you can iterate over string characters to separate letters from number.
http://java11s.blogspot.com/2012/02/java-program-to-separate-alphabets-and.html
Then add result to two separate lists List<String> and List<Double> (or probably List<Integers>) or create custom data structure.
You can try this way :
If we consider that the format of your input is a String in which you want to extract integers, then you should to test one element by one:
Main
public static void main(String[] a) {
List<String> myList = new ArrayList<>();
myList.add("fewf5677");
myList.add("kskfj654");
myList.add("pqoen444");
myList.add("mgnwo888");
List<String> listStrings = new ArrayList<>();
List<Integer> listIntegers = new ArrayList<>();
for (int i = 0; i < myList.size(); i++) {
listStrings.add(getStringPart(myList.get(i)));
listIntegers.add(Integer.parseInt(getIntegerPart(myList.get(i))));
}
System.out.println(listStrings);
System.out.println(listIntegers);
}
Get the string part of your element
private static String getStringPart(String str) {
String s = "";
for (int i = 0; i < str.length(); i++) {
if (!testInteger(str.charAt(i))) {
s += str.charAt(i);
} else {
break;
}
}
return s;
}
Get the Integer part of your element
private static String getIntegerPart(String str) {
String s = "";
for (int i = 0; i < str.length(); i++) {
if (testInteger(str.charAt(i))) {
s += str.charAt(i);
}
}
return s;
}
A method to check if your str is and Integer or not
private static boolean testInteger(char str) {
try {
Integer.parseInt(str+"");
return true;
} catch (Exception e) {
return false;
}
}
Output
[fewf, kskfj, pqoen, mgnwo]
[5677, 654, 444, 888]
Hope this can help you.

Adding Results of Recursion to An ArrayList

I'm trying to find all permutations of a word and add that to an Arraylist and return the array list. But, I believe my recursion is right but, there is a problem with adding the results to the ArrayList.This is what I have so far. The parameters I passed were "eat" and "" and what is returned is "tea" three times
public static ArrayList<String> permutations(String word, String beginning)
{
int l = word.length();
ArrayList<String> temp = new ArrayList<String>();
if(l == 0)
temp.add(beginning + word);
else
{
char c = word.charAt(l-1);
String blah = (beginning + c);
word = word.substring(0, l-1);
for(int i = 0; i < l; i++)
{
permutations(word, blah);
temp.add(blah + word);
}
}
return temp;
}
Probably I didn't have the right idea of your approach to find an easy fix and by the time I got things working I ended up with this. I hope it isn't too much of a departure and that it's still helpful. The output is:
[tea, tae, eta, eat, ate, aet]
import java.util.ArrayList;
public class Perm {
public static void main(String[] args) {
ArrayList<String> perms = new ArrayList<String>();
permutations("tea", perms);
System.out.println(perms);
}
public static ArrayList<String> permutations(String word, ArrayList<String> perms)
{
int l = word.length();
// If the word has only a single character, there is only
// one permutation -- itself. So we add it to the list and return
if (l == 1) {
perms.add(word);
return perms;
}
// The word has more than one character.
// For each character in the word, make it the "beginning"
// and prepend it to all the permutations of the remaining
// characters found by calling this method recursively
for (int i=0; i<word.length(); ++i) {
char beginning = word.charAt(i);
// Create the remaining characters from everything before
// and everything after (but not including) the beginning char
String blah = word.substring(0,i)+word.substring(i+1);
// Get all the permutations of the remaining characters
// by calling recursively
ArrayList<String> tempArray = new ArrayList<String>();
permutations(blah, tempArray);
// Prepend the beginning character to each permutation and
// add to the list
for (String s : tempArray) {
perms.add(beginning + s);
}
}
return perms;
}
}

return multiple values java for removing last part of a word

In my code, fromright method checks the length of last[] and returns only one string. I want to return all matched values. What's the solution?
public static String last[]={"es","e","s"};
public static void main(String[] args) {
text tx=new text();
String checkString = "lives";
String fin=tx.fromright(checkString);
System.out.println("remaining: "+fin);
}
public String fromright(String wrd) {
String tmp="";
for (int i = 0; i < last.length; i++) {
tmp=wrd.substring(0, wrd.length()-last.length);
}
return tmp;
}
You are overriding your tmp variable in your for loop every time. So you can only get one result.
Use this instead or smth. similiar which can hold multiple values.
public List<String> fromright(String wrd) {
List<String> tmp= new ArrayList<String>();
for (int i = 0; i < last.length; i++) {
tmp.add(wrd.substring(0, wrd.length()-last.length));
}
return tmp;
EDIT:
This does not work anymore.
String fin=tx.fromright(checkString);
^
Replace it with
List<String> fin= new ArrayList<String>(tx.fromright(checkString));
And print out all values with this
for(String s : fin) System.out.println(s);
public List<String> fromright(String wrd) {
List<String> result = new ArrayList<>();
for (int i = 0; i < last.length; i++) {
if(wrd.endsWith(last[i]))
result.add(last[i]);
}
return result;

Java Substring by Keyword

I have to make separate Strings from one single String.
For example given the String:
.*C.{0}A.{2}T.{0}T.{0}T.{2}T.{0}G.{8}T.{7}A.{7}T.{2}T.{12}A.{5}T.{4}T.{45}A.{1}A.{10}G.{19}A.{25}T.{3}A.{1}A.{4}G.{1}A.{2}A.{29}A.{0}C.{15}A.{1}C.{1}A.{6}T.{3}G.{5}T.{0}T.{0}C.{3}G.{2}C.{1}G.{4}G.{1}G.*
I have to create a HashSet with the following content:
.*C.{0}A.{2}T.{0}T.*
.*A.{2}T.{0}T.{0}T.*
.*T.{0}T.{0}T.{2}T.*
.*T.{0}T.{2}T.{0}G.*
...
The elements are formed by taking 4 of the entries from the original string and creating a smaller string from them. Then you move one entry along in the original string and repeat.
How can I do this?
Thanks!
You want to take a string, representing a list of elements, and turn it into a set of overlapping shorter lists of elements. You can do this by having a method which returns the elements from the list and then a sliding window which selects sets of elements to display:
private static final Pattern pattern = Pattern.compile("[ACGT]\\.\\{\\d+\\}");
public static List<String> extract(String input) {
Matcher matcher = pattern.matcher(input);
List<String> result = new ArrayList<String>();
while (matcher.find()) {
result.add(matcher.group(0));
}
return result;
}
public static Set<String> compose(List<String> elements, int window) {
Set<String> result = new HashSet<String>();
for (int i = 0; i <= elements.size() - window; i++) {
StringBuilder builder = new StringBuilder(".*");
for (int j = i; j < i + window; j++) {
builder.append(elements.get(j));
}
// This strips the final quantifier turning:
// .*C.{0}A.{2}T.{0}T.{0}
// into
// .*C.{0}A.{2}T.{0}T
builder.delete(builder.lastIndexOf("."), builder.length());
builder.append(".*");
result.add(builder.toString());
}
return result;
}
You can check this with the following method:
public static void main(String[] args) {
String input = ".*C.{0}A.{2}T.{0}T.{0}T.{2}T.{0}G.{8}T.{7}A.{7}";
Set<String> result = compose(extract(input), 4);
// The result will contain
// ".*C.{0}A.{2}T.{0}T.*"
// etc
}
Here is a possible solution:
public class Main {
public static void main(String[] args) {
String s = ".*C.{0}A.{2}T.{0}T.{0}T.{2}T.{0}G.{8}T.{7}A.{7}T.{2}T.{12}A.{5}T.{4}T.{45}A.{1}A.{10}G.{19}A.{25}T.{3}A.{1}A.{4}G.{1}A.{2}A.{29}A.{0}C.{15}A.{1}C.{1}A.{6}T.{3}G.{5}T.{0}T.{0}C.{3}G.{2}C.{1}G.{4}G.{1}G.*";
String[] array = s.split("}");
Set<String> result = new HashSet<String>();
for ( int i = 0 ; i < array.length-3 ; i++) {
String firstElement = array[i].startsWith(".*") ? array[i].substring(2) : array[i];
String lastElement = array[i+2]+"}"+array[i+3].substring(0,1)+".*" ;
String element = ".*"+firstElement+"}"+array[i+1]+"}"+lastElement;
result.add(element);
System.out.println(element);
}
//Your result are in the Set result
}
}

Categories