Reputation: 281
I am currently doing a coding challenge that states:
Given a List of words, return the words that can be typed using letters of alphabet on only one row's of American keyboard like the image below (which is an image of a QWERTY keyboard).
Example:
Input: ["Hello", "Alaska", "Dad", "Peace"]
Output: ["Alaska", "Dad"]
What I have done to solve this is to write a for loop, then do if statements that replace all rows (like QWERTY) to ""
and if the length of this is greater than 1, then you can not type that word in one row. I am getting almost the correct output, but my array contains null elements.
My output is:
[null,"Alaska","Dad",null]
How can I return an array that does not have these null elements? To complete this challenge, I have to return a String[]
array. I can not use an ArrayList
to return.
class Solution {
public String[] findWords(String[] words) {
String[] result = new String[words.length];
String row1 = "qwertyuiop";
String row2 = "asdfghjkl";
String row3 = "zxcvbnm";
for (int i = 0 ; i < words.length; i++) {
if (words[i].toLowerCase().replaceAll("[" + row1 + "]", "").length() == 0 ||
words[i].toLowerCase().replaceAll("[" + row2 + "]", "").length() == 0 ||
words[i].toLowerCase().replaceAll("[" + row3 + "]", "").length() == 0) {
if (words[i] != null) {
result[i] = words[i];
}
}
}
return result;
}
}
Upvotes: 5
Views: 6615
Reputation: 84
One way to reduce the size of an array with null elements is to use the .filter() method. This method will go through each element of the array and check if it is not null. If it is not null, the element will be added to a new array. The new array will then be returned and will only contain the elements that were not null.
Upvotes: 0
Reputation: 5459
You can use the following to remove all nulls from an array of strings:
List<String> list = new ArrayList<String>(Arrays.asList(myArray));
list.removeAll(Collections.singleton(null));
String[] result = list.toArray(new String[list.size()]);
Upvotes: 4
Reputation: 12819
The original problem is that you were returning an Array
that was the same size as the original Array
. So if any of the elements didn't match, one slot in the Array
will be left it's default value, which is null
. You need to keep track of how many items need to be copied over. You can do this with a counter and Arrays.copyOf()
.
Just for what it's worth, Java 8+ we can do:
public static String[] findWords(String[] words) {
return Stream.of("asdfghjkl", "qwertyuiop", "zxcvbnm")
.filter(row -> Arrays.stream(words)
.anyMatch(e -> e.replaceAll("[" + row + "]","")
.isEmpty())
).toArray(String[]::new);
}
Which will create a Stream
of the rows using Stream.of
and filter through the words
Array and only keep the ones that are only made up of letters in a single row on the keyboard
Upvotes: 2
Reputation: 1
Try storing the non-null values in a different variable and count them, initialize another array with the count and copy the values to the latter array. Demonstrated as follows:
class Solution {
public static String[] findWords(String[] words) {
String[] resultWithNull = new String[words.length];
int counter = 0;
String row1 = "qwertyuiop";
String row2 = "asdfghjkl";
String row3 = "zxcvbnm";
for (int i = 0 ; i < words.length; i++) {
if (words[i].toLowerCase().replaceAll("[" + row1 + "]", "").length() == 0 ||
words[i].toLowerCase().replaceAll("[" + row2 + "]", "").length() == 0 ||
words[i].toLowerCase().replaceAll("[" + row3 + "]", "").length() == 0) {
if (words[i] != null) {
resultWithNull[counter] = words[i];
++counter;
}
}
}
String[] result = new String[counter];
for (int i = 0 ; i < counter; i++) {
result[i] = resultWithNull[i];
}
return result;
}
}
Upvotes: 0
Reputation: 251
Using this one liner:
Arrays.stream(result).filter(Objects::nonNull).toArray(String[]::new)
Filters the array and get all objects that are nonNull. Do not forget to transform the stream back to an array.
Upvotes: 6
Reputation: 1627
You could just use an ArrayList instead of an array and then call toArray
at the end if you really need to return a String array.
public String[] findWords(String[] words) {
List<String> result = new ArrayList<>();
String row1 = "qwertyuiop";
String row2 = "asdfghjkl";
String row3 = "zxcvbnm";
for (int i = 0; i < words.length; i++) {
if (words[i].toLowerCase().replaceAll("[" + row1 + "]", "").length() == 0 ||
words[i].toLowerCase().replaceAll("[" + row2 + "]", "").length() == 0 ||
words[i].toLowerCase().replaceAll("[" + row3 + "]", "").length() == 0) {
if (words[i] != null) {
result.add(words[i]);
}
}
}
return result.toArray(new String[0]);
}
Upvotes: 1
Reputation: 72
Your result array is initialized with the size of words array. You can use ArrayList for dynamically assignment.
After you can return ArrayList's toArray method, so that you will return desired striing array.
If you aren't allowed to use ArrayList in the code, I would look for how to size my result array dynamically.
Upvotes: 0