I have 2 string arrays.
string [] first = {"ajunkbc","ajunkHello","adedbc","abcjunk","add","ad","a","","junk","ajunk","aajunkbb"};
String [] second = {"abc","aHello","adedbc","abcjunk","add","ad","a","","junk","a","aajunkbb"};
I'd like the result of my merge() method to concatenate each element from the first array with the respective element of the second array separated by a comma.
Below is my code
private static String[] merge(String [] tests, String [] expectations){
List<String> testList = Arrays.asList(tests);
List<String> expectationsList = Arrays.asList(expectations);
List<String> retList = new ArrayList<String>();
for(String test : testList){
for(String val : expectationsList){
retList.add(test+","+val);
break;
}
}
This does not work. What's wrong with my code?
What's wrong is that you are looping over expectationsList and breaking out of the loop after the first iteration:
for(String val : expectationsList){
retList.add(test+","+val);
break; //<--- breaking out of loop after first iteration each time
}
So the result is that you are always retrieving the first element of expectationsList.
Since what you want is to loop over two arrays, you should use an index:
for (int i = 0; i < testList.size(); i++) {
retList.add(testList.get(i)+","+expectationsList.get(i));
}
Also, note that this implies that the size of testList is the same as the size of expectationsList. Your method should probably throw an exception if this is not the case.
Note that you do not need to convert the input arrays into lists. You can use them as-is.
private static String[] merge(String[] tests, String[] expectations) {
if (tests.length != expectations.length) {
throw new IllegalArgumentException("input not of same length");
}
String[] result = new String[tests.length];
for (int i = 0; i < tests.length; i++) {
result[i] = tests[i] + "," + expectations[i]);
}
return result;
}
Java 8 solution:
private static String[] merge(String[] tests, String[] expectations) {
if (tests.length != expectations.length) {
throw new IllegalArgumentException("input not of same length");
}
return IntStream.range(0, tests.length).mapToObj(i -> tests[i] + "," + expectations[i]).toArray(String[]::new);
}
You're iterating through each member of testList and then for each one, iterating through each member of expectationsList. You want to iterate through each of both of them together.
What you want to do is something like this:
private static String[] merge(String[] tests, String[] expectations) {
String[] result = new String[tests.length];
for(int i = 0; i < tests.length; i++) {
result[i] = tests[i] + "," + expectations[i];
}
return result;
}
This code makes the assumption that tests and expectations have the same length. You might want to do a check for that at the beginning:
if (tests.length != expectations.length) {
throw new IllegalArgumentException("tests and expectations are of different lengths")
}
Notice how now you're getting the element at the same index from both arrays.
Sidenote: You can iterate over arrays with the for each format. This works just fine:
String[] myStringArray = getStringArray();
for (String myString : myStringArray) {
// Do something
}
You don't need to convert to a List in order to iterate :)
Related
I am trying to use a method that accepts an integer and then a string and returns a string array. The string is split using a comma delimiter. Each element of the array is supposed to be defaulted to empty before storing the data split by the delimiter.
My question is what would I put into the for loop to receive that output? or is the for loop even necessary.
This is what I have so far:
public static String[] parseString(int arraySize, String input) {
String[] array = input.split(", ");
for (int i = 0; i < arraySize; i++) {
}
return array;
}
This is an example of how it is called in the main:
String[] result;
result = Utility.parseString(3, "apple, pear, peach, plum, kiwi");
for (int i = 0; i < result.length; i++) {
System.out.println(i + ". [" + result[i] + "]");
}
and this is an example of the correct output:
0. [apple]
1. [pear]
2. [peach]
Compared to my output right now.
0. [apple]
1. [pear]
2. [peach]
3. [plum]
4. [kiwi]
You need the array to have arraySize elements. split will give you an array with just the right number of elements, or fewer/more elements than you need. You can handle each of these cases separately. In the latter case, you use a for loop to copy the elements in array to a new array with length arraySize.
String[] array = input.split(", ");
if (array.length == arraySize) {
return array;
} else {
String[] newArray = new String[arraySize];
for (int i = 0 ; i < arraySize ; i++) {
if (i < array.length) {
newArray[i] = array[i];
} else { // this will be reached if split gave us fewer elements than we need
newArray[i] = "";
}
}
return newArray;
}
Alternatively, you can use the helpful methods in Arrays:
String[] array = input.split(", ");
if (array.length == arraySize) {
return array;
} else if (array.length < arraySize) { // split gave us fewer elements than we need
// this produces a copy of the array, with extra nulls at the end of the array
String[] newArray = Arrays.copyOf(array, arraySize);
// so we fill those nulls with ""
Arrays.fill(newArray, array.length, arraySize, "");
return newArray;
} else { // split gave us more elements than we need, copyOf will do exactly what we want
return Arrays.copyOf(array, arraySize);
}
Your method parseString must be like this:
public static String[] parseString(int arraySize, String input)
{
String[] array = new String[arraySize]
String [] aux = input.split(", ");
for(int i=0;i<arraySize; i++)
{
array[i] = aux[i];
}
return array;
}
But, you must be careful, because the code input.split(", ") can return a length which can cause en ArrayIndexOutOfBoundException
I mean that when you try to access to aux[i] can be possible that the i value it's is greater or equal than aux.length
With the introduction of Java Streams, you could make your code simpler,
less error-prone and more self-explanatory.
Try this, please:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
class Main {
public static void main(String[] args) {
List<String> result = parseString(3, "apple, pear, peach, plum, kiwi", ",");
IntStream.range(0, result.size())
.forEach(idx -> System.out.println(idx + ". [" + result.get(idx) + "]"));
}
private static List<String> parseString(int arraySize, String input, String delimiter) {
return Arrays.stream(input.split(delimiter))
.map(String::trim)
.limit(arraySize)
.collect(Collectors.toList());
}
}
Resources
Java Streams
stream()
https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html
https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html
limit()
https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html#limit-long-
collect()
https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html#collect-java.util.stream.Collector-
forEach()
https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html#forEach-java.util.function.Consumer-
IntStream
https://docs.oracle.com/javase/8/docs/api/java/util/stream/IntStream.html
intstream.range()
https://docs.oracle.com/javase/8/docs/api/java/util/stream/IntStream.html#range-int-int-
Good luck!
I wanted to create an algorithm in java where I can pass a list of strings and it returns a new list with all possible combinations of the strings it has in the list.
Example:
String[] listWords = new String[] {
"windows",
"linux",
"mac",
"10",
"20"
};
I would like to call a method by passing the list that returns all possible combinations, in all orders.
combinations(listWords);
This is the result I wanted to have:
windows,linux,mac,10,20,windowslinux,linuxwindows,windowsmac,windows10,10windows,windows20,20windows,windowslinuxmac1020,windowsmaclinux20,mac10,mac20,20mac,20mac10,windowsmac,macwindows...
I tried this:
public String[][] combinations (String[] ports) {
List<String[]> combinationList = new ArrayList<String[]>();
for ( long i = 1; i < Math.pow(2, ports.length); i++ ) {
List<String> portList = new ArrayList<String>();
for ( int j = 0; j < ports.length; j++ ) {
if ( (i & (long) Math.pow(2, j)) > 0 ) {
portList.add(ports[j]);
}
}
combinationList.add(portList.toArray(new String[0]));
}
return combinationList.toArray(new String[0][0]);
}
But this returns:
This was not how I wanted it. The result had to be:
list: [windows, linux, windowslinux, linuxwindows, windows10, 10windowsmaclinux...]
Is it possible to do this in java? thank you who can help :)
If I've understood you correctly, the following will solve the problem.
You can build the result iteratively starting from the list of words that you have, and in each iteration you add longer and longer words. The first iteration gives you the original list. The second iteration adds one new word to each, giving you the permutations of 2 words. The third iteration adds one new word to each of those, giving you the permutations of 3 words, and so on.
List<String> getWordPermutations(List<String> words) {
List<String> result = new ArrayList<>(words);
List<String> oldPermutations = new ArrayList<>(words);
for (int i = 1; i < words.size(); i++) {
List<String> newPermutations = new ArrayList<>();
for (String previousList : oldPermutations) {
for (String word : words) {
if (previousList.contains(word)) {
continue;
}
newPermutations.add(previousList + word);
}
}
oldPermutations = newPermutations;
result.addAll(newPermutations);
}
return result;
}
I have the following bunch of arrays:
public class ArrayPermutationExample {
private static final String PREFIX = "ignore(FAILURE) { build(\"load\", ";
public static final String ENDING = ")}";
private static String[] arr_1 = new String[] {
"111",
"222",
"333"};
private static String[] arr_2 = new String[]{
"aaa",
"bbb",
"ccc"};
private static String[] arr_3 = new String[] {
"***",
"&&&",
"$$$"};
I need to find permutation with other arrays, excluding native array.
The output should look like:
111aaa
111bbb
111ccc
111***
111&&&
111$$$
222aaa
222bbb
222ccc
...
333aaa
333bbb
333ccc
...
Finally, for all those permutations should be added prefix and ending:
prefix permutation string endings
And at the end we should have something like:
ignore(FAILURE) { build("load", 111aaa )}
I completely stuck with a solution for this task:
private static void processArrays(String[] ... arrays) {
ArrayList<String> result = new ArrayList<>();
for (String[] array : arrays) {
String[] currentArray = array;
for (String line : currentArray) {
// exclude all lines from current array & make concatenation with every line from others
}
}
}
How to solve this issue?
UPDATE:
I want to add that finally, we need to have a distinct list without any dublications. Even following example will be duplicating each other:
111aaa***
***111aaa
I believe that this task should have a solution with Java 8 style.
I think this may be a combination since you don't actually care about getting all orderings (other than printing in the order specified by the order of the array parameters), but regardless, here is the code I wrote. I used a stack for storing unfinished arrays. Pushing to the stack each possibility at any given point for every array and pushing to results for any completed array.
public static List<String> getCombinations(String prefix, String ending, String[]... arrays) {
List<String> results = new ArrayList<>();
Stack<String[]> combinations = new Stack<>();
combinations.add(new String[arrays.length]);
while (!combinations.isEmpty()) {
String[] currentArray = combinations.pop();
if (currentArray[arrays.length - 1] == null) {
for (int i = 0; i < arrays.length; i++) {
if (currentArray[i] == null) {
for (int j = 0; j < arrays[i].length; j++) {
String[] newArray = currentArray.clone();
newArray[i] = arrays[i][j];
combinations.add(newArray);
}
break;
}
}
} else {
StringBuilder stringBuilder = new StringBuilder(prefix);
for (String string : currentArray) {
stringBuilder.append(string);
}
stringBuilder.append(ending);
results.add(stringBuilder.toString());
}
}
return results;
}
You would just need to iterate over the returned list to print out all of the strings.
As an added note, this method could be written recursively, but I usually like using a stack instead of using recursion when possible because recursion can be slow sometimes.
The way I read it: the first array arr_1 is prepended to the next 3 arrays.
I think the prefix is "ignore(FAILURE) { build("load", " and the ending is "}}"
String prefix = "ignore(FAILURE) { build(\"load\", ";
String ending = "}}";
for (String first: arr_1) {
for (String second: arr_2) {
System.out.println( prefix + first + second + ending);
}
for (String second: arr_3) {
System.out.println( prefix + first + second + ending);
}
for (String second: arr_4) {
System.out.println( prefix + first + second + ending);
}
}
I have a sorted array list with 6 elements.The first 5 elements have some value, and the 6th one is empty.
I want to loop through this ArrayList, and compare the first 5 elements of first record, with the same elements in next record. If any one of the element is different, then populate 6th element.
Anyone know an easier and faster approach to do that?
Thanks
Angad
First split the all records into many String[], then parse all values in each. After that you can compare the current record with the first one. Here is an example:
public class StringComparison {
ArrayList<String[]> list = new ArrayList<String[]>();
public void comapreStrings() {
// The list you are comparing everything to
String[] firstRecord = list.get(0);
for(int n = 1; n < list.size(); n++) {
String[] currentRecord = list.get(n);
for (int i = 0; i < currentRecord.length; i++) {
String val1 = firstRecord[i];
String val2 = currentRecord[i];
if (val1.equals(val2)) {
// The two strings are the same
} else {
// Replace "a value" with whatever you want to fill the 6th element with
currentRecord[5] = "a value";
}
}
}
}
Maybe this could be an alternative to think about:
public String[] generateFirstRow(int startingRow) {
final String[] row1 = rowList.get(startingRow);
final String[] row2 = rowList.get(startingRow + 1);
final List<String> list1 = Arrays.stream(row1).collect(toList());
final List<String> toAdd = Arrays.stream(row2).parallel().sorted().filter(s -> !list1.contains(s)).collect(Collectors.toList());
if (list1.get(list1.size() - 1) == "") {
list1.set(list1.size() - 1, toAdd.get(0));
return list1.toArray(new String[0]);
}
return new String[0];
}
Now you can call this per row you have untill the pre-last one.
Below are the 2 ways to remove null values, which one is the best approach?
public static String[] clean(final String[] v) {
List<String> list = new ArrayList<String>(Arrays.asList(v));
list.removeAll(Collections.singleton(null));
return list.toArray(new String[list.size()]);
}
public static String[] clean(final String[] v) {
List<String> list = new ArrayList<String>(v.length);
for (String aString : v)
{
if (aString != null)
{
list.add(aString);
}
}
return list.toArray(new String[list.size()]);
}
For removing null values from a single string, I would use a regular expression like this,
private static Pattern pattern = Pattern.compile("(?i)[(\\[{]?null[)\\]}]?");
public static String removeNullString(String value) {
if (StringUtils.isEmpty(value)) {
return StringUtils.EMPTY;
}
Matcher matcher = pattern.matcher(value);
return matcher.replaceAll(StringUtils.EMPTY);
}
It covers up all "null" and empty character from string.
For removing null value from a string array in Java 7,
String[] firstArray = {"test1", "", "test2", "test4", "", null};
List<String> list = new ArrayList<String>();
for(String s : firstArray) {
if(s != null && s.length() > 0) {
list.add(s);
}
}
firstArray = list.toArray(new String[list.size()]);
For removing null value from a string array in Java 8,
String[] firstArray = {"test1", "", "test2", "test4", "", null};
firstArray = Arrays.stream(firstArray)
.filter(s -> (s != null && s.length() > 0))
.toArray(String[]::new);
Performance wise, it is usually better to minimize calls outside of the scope of the current code block (ie method). Also, since memory allocation is relatively slow compared most other instructions, avoiding object creation is typically a goal. The best I can come up with in terms of performance (I chose to make it flexible enough to take any type of array):
public <T> T[] removeNulls(Class<T> type, final T[] original){
// first, shift all non-null instances to the head, all nulls to the end.
int nonNullCount=0;
T tempT = null;
for(int i=0; i < original.length; i++){
if(original[i] != null){
nonNullCount++;
}else if(i != original.length - 1){
// Swap the next non-null value with this null value
int j = i + 1;
// In case there are multiple null values in a row
// scan ahead until we find the next non-null value
while(j < original.length && (tempT = original[j]) == null){
j++;
}
original[nonNullCount] = tempT;
if(tempT != null){
nonNullCount++;
}
if(j < original.length){
original[j] = null;
}
i = j - 1;
}
}
// The case where there are no nulls in the array
if(nonNullCount == original.length){
return original;
}
final T[] noNulls = (T[]) Array.newInstance(type,nonNullCount);
System.arraycopy(original,0,noNulls,0,nonNullCount);
return noNulls;
}
But I'm not sure why you would want this complexity over the 3 or 4 lines to do the same thing when performance is not likely to be an issue. You would need to have HUGE arrays to see any benefit (if any) between my code and your clean example.
in Java 8 you should be able to do something like:
List<String> list = new ArrayList<String>(Arrays.asList(v));
list.removeIf(Objects::isNull);
return list.toArray(new String[list.size()]);
if you want to do it in same space i will suggest the follwing solution. But final array will also be having same size. I mean it will not shrink in size but all elements will get aggregated in same order.
public static void removeNullFromArray(String[] args) {
int location = 0;
for(int i=0; i<args.length; i++){
String arg = args[i];
if(arg!=null){
if(location<i){
args[location] = arg;
args[i] = null;
}
location++;
}
}
}
Java 8 code using streams and lambda. Filters non-nulls from an array and converts to a list.
Arrays.stream(arr).filter(Objects::nonNull).collect(Collectors.toList());