I've been trying to get each character from every String by column but I only got the first characters of every string, I want to get every character by column from every string.
For example:
I have three strings from ArrayList of Strings:
chi
llo
ut
What I want to happen must be like this, after getting each character by column from strings:
clu
hlt
io
So long, my current source code only gets the first characters of first two string which is 'cl', Here's my current source code:
List<String> New_Strings = new ArrayList<String>();
int Column_Place = 0;
for (String temp_str : Strings) {
try{ //For StringIndexOutOfBoundsException (handle last String)
if(Column_Place >= temp_str.length()){
Current_Character = temp_str.charAt(Column_Place);
New_Strings.add(Character.toString(Current_Character));
break;
}else if (Column_Place < temp_str.length()){
Current_Character = temp_str.charAt(Column_Place);
New_Strings.add(Character.toString(Current_Character));
}
}catch(Exception e){
continue;
}
Column_Place++;
}
You're adding string representations of the individual characters to the result string. Instead, you should accumulate these characters in to a result string. E.g.:
int numStrings = strings.size();
List<String> result = new ArrayList<>(numStrings);
for (int i = 0; i < numStrings; ++i) {
StringBuilder sb = new StringBuilder();
for (String s : strings) {
if (i < s.length) {
sb.append(s.charAt(i));
}
}
result.add(sb.toString());
}
Just call groupByColumn(Arrays.asList("chi", "llo", "ut"):
public static List<String> groupByColumn(List<String> words) {
if (words == null || words.isEmpty()) {
return Collections.emptyList();
}
return IntStream.range(0, longestWordLength(words))
.mapToObj(ind -> extractColumn(words, ind))
.collect(toList());
}
public static String extractColumn(List<String> words, int columnInd) {
return words.stream()
.filter(word -> word.length() > columnInd)
.map(word -> String.valueOf(word.charAt(columnInd)))
.collect(Collectors.joining(""));
}
public static int longestWordLength(List<String> words) {
String longestWord = Collections.max(words, Comparator.comparing(String::length));
return longestWord.length();
}
You iterate on the List with a enhanced/foreach loop.
So you will iterate a single time on each
String. Whereas your result : only the first letters are hanlded.
You should use a while loop with as while condition while(Column_Place < Strings.size()) with such an approach.
Or as alternative you could do things in two distinct steps and use Java 8 features.
Note that in Java, variables starts with lowercase. Please follow the conventions to make your code more readable/understandable here and there.
In Java 8 you could do :
List<String> strings = new ArrayList<>(Arrays.asList("chi", "llo", "ut"));
int maxColumn = strings.stream()
.mapToInt(String::length)
.max()
.getAsInt(); // suppose that you have at least one element in the List
List<String> values =
// stream from 0 the max number of column
IntStream.range(0, maxColumn)
// for each column index : create the string by joining their
// String value or "" if index out of bound
.mapToObj(i -> strings.stream()
.map(s -> i < s.length() ? String.valueOf(
s.charAt(i)) : "")
.collect(Collectors.joining()))
.collect(Collectors.toList());
just think the list as two dimensional array. split each item from the list, get the j-th character from each item, if and only if the item's length is greater than the index j.
ArrayList<String> list = new ArrayList<String>();
list.add("chi");
list.add("llo");
list.add("ut");
int size = list.size();
int i=0, j=0,k=0;
while(size-- > 0){
for(i=0; i<list.size(); i++){
String temp = list.get(i);
if(j < temp.length()){
System.out.print(temp.charAt(j));
}
}
j++;
System.out.println();
}
Related
I have a string which I want to split after every n characters and store the same in an array of strings, but this should ignore all the whitespaces.
For example I have a string as follows,
String str = "This is a String which needs to be splitted after every 10 characters";
The output should be,
["This is a Str", "ing which nee", "ds to be split", "ted after ev", "ery 10 chara", "cters"]
(Edit) --> I am using the function below. How can I store this in an array of Strings.
As seen in the output it ignores indexes of all the whitespaces. Is there any way to do it in java.
public static String test(int cnt, String string) {
AtomicInteger n = new AtomicInteger(cnt);
return string
.chars()
.boxed()
.peek(value -> {
if (!Character.isWhitespace(value)) {
n.decrementAndGet();
}
})
.takeWhile(value -> n.get() >= 0)
.map(Character::toString)
.collect(Collectors.joining());
I have used a standard approach with looping through the string and counting chars:
public static void main(String[] args) throws ParseException {
String str = "This is a String which needs to be splitted after every 10 characters";
System.out.println(split(str, 10));
}
public static List<String> split(String string, int splitAfter) {
List<String> result = new ArrayList<String>();
int startIndex = 0;
int charCount = 0;
for (int i = 0; i < string.length(); i++) {
if (charCount == splitAfter) {
result.add(string.substring(startIndex, i));
startIndex = i;
charCount = 0;
}
// only count non-whitespace characters
if (string.charAt(i) != ' ') {
charCount++;
}
}
// check if startIndex is less than string length -> if yes, then last element wont be 10 characters long
if (startIndex < string.length()) {
result.add(string.substring(startIndex));
}
return result;
}
And the result differs slightly from what you posted, but looking at your expected result, it doesn't quite match the description anyways:
[This is a Str, ing which ne, eds to be spl, itted after, every 10 cha, racters]
I am trying to generate permutations using list of strings taking one character one time.
Below is the code of input and output that I want.
Can we simply do it iteratively?. Also I am not finding exact method.
String[] lst = new String[]{"abc", "def", "ghi"}; //Given
String[] permutations = new String[]{ //To Generate
"adg", "adh", "adi",
"aeg", "aeh", "aei",
"afg", "afh", "afi",
"bdg", "bdh", "bdi",
"beg", "beh", "bei",
"bfg", "bfh", "bfi",
"cdg", "cdh", "cdi",
"ceg", "ceh", "cei",
"cfg", "cfh", "cfi",
};
Update: I am not looking just for the above example with list size=3. It can be of any size and each string may happen to be of different length.
For ex: list = [ "ab", "abc", "defghi", "x", "einsigl"]
In this answer I will walk through how I solved this problem to find an algorithm that works for an array of any length for words which can be any length and are not required to all be the same length.
I will first make a recursive solution, and then transorm it into an iterative one.
The easiest way to answer problems like this is to think of them recursively:
Generating all permutations of [] should return [""]
Generating all permutations of a non-empty list means, for each letter c in the first word in the list, return all permutations of the rest of the list with c prepended on the front.
This can be written in Java as follows:
public static List<String> generatePermutationsRecursiveSlow(String[] words) {
if (words.length == 0)
// base case
return Collections.singletonList("");
else {
// recursive case
// result list
ArrayList<String> permutations = new ArrayList<>();
// split array into item 0 and items [1..end]
String firstWord = words[0];
String[] otherWords = new String[words.length - 1];
System.arraycopy(words, 1, otherWords, 0, words.length - 1);
// recurse to find permutations for items [1..end]
List<String> otherWordsPermutations = generatePermutationsRecursiveSlow(otherWords);
// for each character in the first word
for (char c : firstWord.toCharArray()) {
// for each permutation from the recursive call's results
for (String otherWordsPermutation : otherWordsPermutations) {
// prepend this character onto the permutation and add it to the results
permutations.add(c + otherWordsPermutation);
}
}
return permutations;
}
}
Calling generatePermutationsRecursiveSlow(new String[0]) returns [""].
Calling generatePermutationsRecursiveSlow(new String[]{"cd"}) will cause the local c variable to be equal to 'c', and it will recurse with an empty array as the argument, making otherWordsPermutations equal to [""], so it will add 'c' + "" (which is "c") to the results, then it will do the same for 'd', adding "d" to the results.
Calling generatePermutationsRecursiveSlow(new String[]{"ab", "cd"}) will mean that when c is 'a', it will add to the results list 'a'+"c", then 'a'+"d", and whencis'b', it will add'b'+"c"and'b'+"d"`
A similar but better optimised version which works in the same way can be written like this:
public static List<String> generatePermutationsRecursive(String[] words) {
ArrayList<String> permutations = new ArrayList<>();
int wordLen = words.length;
generatePermutationsRecursive(words, permutations, new char[wordLen], 0);
return permutations;
}
public static void generatePermutationsRecursive(String[] words, ArrayList<String> permutations, char[] word, int i) {
if (i == word.length) {
// base case
permutations.add(new String(word));
} else {
for (int j = 0; j < words[i].length(); j++) {
// equivalent of prepending
word[i] = words[i].charAt(j);
// recurse
generatePermutationsRecursive(words, permutations, word, i + 1);
}
}
}
This is better optimised since it uses the word parameter to avoid the O(n) prepending to the string by instead modifying a character array. It also introduces the parameter i which is the effective start index of the array, making it possible to avoid copying parts of the input array.
This can be transformed into an iterative approach by tracking the variables that change between different recursive calls using a stack (in place of the call stack):
private static List<String> generatePermutationsIterative(String[] words) {
// in the recursive version, each recursive function call would have its own local copy of `i` and `j`
// simulate that here with 2 stacks
ArrayDeque<Integer> i_stack = new ArrayDeque<>(words.length);
ArrayDeque<Integer> j_stack = new ArrayDeque<>(words.length);
i_stack.add(0);
j_stack.add(0);
char[] word = new char[words.length];
ArrayList<String> permutations = new ArrayList<>();
while (!i_stack.isEmpty()) {
int i = i_stack.removeLast();
int j = j_stack.removeLast();
if (i == words.length) {
// base case
permutations.add(new String(word));
continue;
}
if (!(j < words[i].length())) {
// reached end of loop `for (int j = 0; j < words[i].length(); j++)`
continue;
}
// if not reached end of loop `for (int j = 0; j < words[i].length(); j++)` yet,
// then increment `j` and allow next iteration to happen
i_stack.add(i);
j_stack.add(j + 1);
word[i] = words[i].charAt(j);
// recurse
i_stack.add(i + 1);
j_stack.add(0);
}
return permutations;
}
Code here
As a sidenote, look how cool Haskell is with this 2-line solution to the problem here (admittedly its not iterative, but it should have tail-call optimisation, making it as fast as an iterative solution).
Here's one way to do it that should work for arbitrary number of words of arbitrary length (not including 0).
String[] lst = new String[] {
"abc",
"def",
"ghi"
};
int numWords = lst.length;
int wordlen = lst[0].length();
int numPerms = (int) Math.pow(wordlen, numWords);
char[][] perms = new char[numPerms][numWords];
char[][] chararr = Arrays.stream(lst)
.map(String::toCharArray)
.toArray(i -> new char[i][wordlen]);
for (int i = 0; i < numWords; i++) {
double permsLocal = Math.pow(wordlen, i + 1);
int numRepeats = (int) Math.ceil((numPerms / permsLocal));
int repeats = (int)(permsLocal / wordlen);
for (int x = 0; x < repeats; x++) {
char[] word = chararr[i];
for (int j = 0; j < wordlen; j++) {
char c = word[j];
for (int k = 0; k < numRepeats; k++) {
perms[(x * wordlen * numRepeats) + k + j * numRepeats][i] = c;
}
}
}
}
String[] permutations = Arrays.stream(perms)
.map(String::new)
.toArray(String[]::new);
Output:
[adg, adh, adi, aeg, aeh, aei, afg, afh, afi, bdg, bdh, bdi, beg, beh,
bei, bfg, bfh, bfi, cdg, cdh, cdi, ceg, ceh, cei, cfg, cfh, cfi]
Link to repl.it: https://repl.it/repls/BoilingExcitingAttributes
You can do it as follows:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Main {
public static void main(String[] args) {
String[] lst = new String[] { "abc", "def", "ghi" };
List<String> list = new ArrayList<>();
for (char a : lst[0].toCharArray()) {
for (char b : lst[1].toCharArray()) {
for (char c : lst[2].toCharArray()) {
list.add(new String(new char[] { a, b, c }));
}
}
}
// Convert to array
String[] permutations = list.toArray(new String[0]);
// Display
System.out.println(Arrays.toString(permutations));
}
}
Output:
[adg, adh, adi, aeg, aeh, aei, afg, afh, afi, bdg, bdh, bdi, beg, beh, bei, bfg, bfh, bfi, cdg, cdh, cdi, ceg, ceh, cei, cfg, cfh, cfi]
I have the following string:
String string = "bbb,aaa,ccc\n222,111,333\nyyy,xxx,zzz";
And I'm trying to convert it to:
String converted = "aaa,bbb,ccc\n111,222,333\nxxx,yyy,zzz";
To be somehow sorted. This is what I have tried so far:
String[] parts = string.split("\\n");
List<String[]> list = new ArrayList<>();
for(String part : parts) {
list.add(part.split(","));
}
for(int i = 0, j = i + 1, k = j + 1; i < list.size(); i++) {
String[] part = list.get(i);
System.out.println(part[i]);
}
So I managed to get first element from each "unit" separately. But how to get all and order them so I get that result?
Can this be even simpler using Java8?
Thanks in advance!
I guess one way to do it would be:
String result = Arrays.stream(string.split("\\n"))
.map(s -> {
String[] tokens = s.split(",");
Arrays.sort(tokens);
return String.join(",", tokens);
})
.collect(Collectors.joining("\\n"));
System.out.println(result); // aaa,bbb,ccc\n111,222,333\nxxx,yyy,zzz
Just notice that in case your patterns are more complicated than \n or , - it is a good idea to extract those an separate Pattern(s)
String string = "bbb,aaa,ccc\n222,111,333\nyyy,xxx,zzz";
String converted = Arrays.stream(string.split("\\n"))
.map(s -> Arrays.stream(s.split(","))
.sorted()
.collect(Collectors.joining(",")))
.collect(Collectors.joining("\\n"));
You can have it the old fashioned way without the use of Java 8 like this:
public static void main(String[] args) {
String s = "bbb,aaa,ccc\n222,111,333\nyyy,xxx,zzz";
System.out.println(sortPerLine(s));
}
public static String sortPerLine(String lineSeparatedString) {
// first thing is to split the String by the line separator
String[] lines = lineSeparatedString.split("\n");
// create a StringBuilder that builds up the sorted String
StringBuilder sb = new StringBuilder();
// then for every resulting part
for (int i = 0; i < lines.length; i++) {
// split the part by comma and store it in a List<String>
String[] l = lines[i].split(",");
// sort the array
Arrays.sort(l);
// add the sorted values to the result String
for (int j = 0; j < l.length; j++) {
// append the value to the StringBuilder
sb.append(l[j]);
// append commas after every part but the last one
if (j < l.length - 1) {
sb.append(", ");
}
}
// append the line separator for every part but the last
if (i < lines.length - 1) {
sb.append("\n");
}
}
return sb.toString();
}
But still, Java 8 should be preferred in my opinion, so stick to one of the other answers.
The Pattern class gives you a possibility to stream directly splitted Strings.
String string = "bbb,aaa,ccc\n222,111,333\nyyy,xxx,zzz";
Pattern commaPattern = Pattern.compile(",");
String sorted = Pattern.compile("\n").splitAsStream(string)
.map(elem -> commaPattern.splitAsStream(elem).sorted().collect(Collectors.joining(",")))
.collect(Collectors.joining("\n"));
I need some help, I have two Strings and I want to get the first occurrence of common substrings.
1st String : abacdefghi
2nd String : abaciopiss
I want to get the substring
substring : abac
Thank you everyone.
It maybe isn't the best solution but my attempt would be to find the first matching characters in each string and then continue to check the following characters if they are still the same:
private static String extractFirstEqual(String a, String b) {
//Split your string into an array of characters
String[] arr = a.split("");
String[] brr = b.split("");
StringBuilder result = new StringBuilder();
//Iterate over both arrays
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < brr.length; j++) {
//Find first matching character
if (arr[i].equals( brr[j])) {
//While there are more characters in both arrays and the characters keep matching, append them
// to the result
while (arr[i].equals(brr[j]) && i < arr.length && j < brr.length) {
result.append(arr[i]);
i++;
j++;
}
return result.toString();
}
}
}
return result.toString();
}
I facing some issue with write logic for below problem.
I have two ArrayLists of strings:
List1: contains 5 million strings
List2: will create on users input and contains some strings/characters(Ex. a,b,c,g,l,pd,sp,mta)
Now I have to split list1 into multiple Lists according to startsWith strings in list2 like in above case. I need to create 8 lists as starts with 'a', 'b','c', 'g', 'l','pd', 'sp' and 'mta'
But the condition for above is I have to iterate List1 or List2 only once. i.e. worst complexity for algorithm should be size of List1 (5 million).
It is allowed to use collections.sort() method
Code I have tried
// Create List for search strings.
List<String> CharList = new ArrayList<String>();
CharList.add("a");
CharList.add("b");
CharList.add("e");
CharList.add("z");
CharList.add("4");
CharList.add("1");
CharList.add("zi");
List<String> recordList = new ArrayList<String>();
// Creating dummy data with 100 character in live environment it can be
// around 50 lakhs strings
for (int i = 0; i < 100; i++) {
char[] chars = "abcdefghijklmnopqrstuvwxyzABCGDKL0123456789".toCharArray();
StringBuilder sb = new StringBuilder();
Random random = new Random();
for (int i1 = 0; i1 < 6; i1++) {
char c = chars[random.nextInt(chars.length)];
sb.append(c);
}
String output = sb.toString();
recordList.add(output);
}
// Adding some data mannually
recordList.add("zink");
recordList.add("zebra");
recordList.add("zzzzzz");
Collections.sort(CharList, String.CASE_INSENSITIVE_ORDER);
Collections.sort(recordList, String.CASE_INSENSITIVE_ORDER);
System.out.println("RECORDLIST ===>" + recordList);
System.out.println("***************************************************");
System.out.println("Charlist ===>" + CharList);
System.out.println("***************************************************");
List<List> lists = new ArrayList<List>();
int startIndex = 0, charPointer = 0;
while (startIndex < recordList.size() && charPointer < CharList.size()) {
List<String> temp = new ArrayList<String>();
boolean isHit = false;
String currentRecord = recordList.get(startIndex);
String partitionSattement = CharList.get(charPointer);
while (currentRecord.startsWith(partitionSattement.toUpperCase())
|| currentRecord.startsWith(partitionSattement.toLowerCase())) {
temp.add(recordList.get(startIndex));
isHit = true;
startIndex++;
}
if (!isHit) {
startIndex++;
}
if (!temp.isEmpty()) {
lists.add(temp);
System.out.println(CharList.get(charPointer) + "====>" + temp);
}
charPointer++;
}
Just using the String startsWith method won't work in this case. Consider what happens if the first pattern does not match any input - you'll loop through all strings in the input list without finding a match, even though subsequent pattern matches do exist.
What we need to do instead is compare each pattern against the initial characters of each input string and process accordingly. Let's say we have an input string str and a pattern pat. Let subStr be the first pat.length() characters of str. Now we can compare subStr and pat using the String compareToIgnoreCase method. There are three cases to consider:
subStr < pat Move to the next input string.
subStr == pat Add str to output for pat and move to the next input string.
subStr > pat Move to the next pattern.
Here's some code to illustrate (I've kept your variable names where possible).
List<List<String>> output = new ArrayList<>();
for(int i=0; i<CharList.size(); i++) output.add(new ArrayList<String>());
int startIndex=0;
int charPointer=0;
while(startIndex < recordList.size() && charPointer < CharList.size())
{
String charStr = CharList.get(charPointer);
String recStr = recordList.get(startIndex);
int cmp;
if(recStr.length() < charStr.length())
{
cmp = -1;
}
else
{
String recSubStr = recStr.substring(0, charStr.length());
cmp = recSubStr.compareToIgnoreCase(charStr);
}
if(cmp <= 0)
{
if(cmp == 0) output.get(charPointer).add(recStr);
startIndex++;
}
else
{
charPointer++;
}
}
for(int i=0; i<CharList.size(); i++)
{
System.out.println(CharList.get(i) + " : " + output.get(i));
}
Also, you should note that when you include a pattern that itself starts with another pattern (e.g. "zi" and "z") the longer pattern will never be matched, since the shorter one will capture all inputs.
I can see two problems in your code:
You should remove the following segment:
if (!isHit) {
startIndex++;
}
Actually you don't need that isHit variable at all. If a string doesn't match with a pattern then you still have to compare it with the next pattern.
You should sort the arrays in descending order. As SirRaffleBuffle noted in the other answer you should compare the strings with the longer pattern first. Sorting the strings and patterns in descending order will automatically solve this problem.