How to create a shorter array based on another? - java

I have an array like this (source)
[Maria Carolina, Luisa Joana, Lara Silva, Catarina Patricio, Paula Castro, fim, null, null, null]
and I want an array like that (destination)
[Maria Carolina, Luisa Joana, Lara Silva, Catarina Patricio, Paula Castro]
In the following code i is the number of names.
My code is:
String[] nomeCompleto = new String[10];
String[] nomes = new String[10-i];
if(i < 10) {
nomes[i] = nomeCompleto[i];
}
System.out.println(Arrays.toString(nomes));
return;
What am I doing wrong?

Edit: The question presents a source code fragment based on array indices, hence my original answer:
Use the Arrays class to do this for you.
String[] names = new String[] {"Maria Carolina", "Luisa Joana", "Lara Silva", "Catarina Patricio", "Paula Castro", "fim", null, null, null};
String[] truncated = java.util.Arrays.copyOf(names, names.length-4); // remove the last 4 names
System.out.println(java.util.Arrays.toString(truncated));
Try it online here.
Edit: Since people (not the OP) weren't too happy with that, I added: Or, to match only names of the form Firstname Lastname, use a regex:
String[] input = new String[] {"Maria Carolina", "Luisa Joana", "Lara Silva", "Catarina Patricio", "Paula Castro", "fim", null, null, null};
List<String> namesList = new ArrayList<>();
for(String name : input) {
if(name != null && name.matches("^[A-Z][A-z]+ [A-Z][a-z]+$"))
namesList.add(name);
}
String[] namesArray = namesList.toArray(new String[0]);
System.out.println(Arrays.toString(namesArray));
Try it online here.
Edit: Finally, since Dukeling commented on fim meaning end in Portuguese, a better solution might be:
Use a loop to find the first occurrence of fim and then truncate the array accordingly (as in the first code snippet in my answer).
String[] names = new String[] {"Maria Carolina", "Luisa Joana", "Lara Silva", "Catarina Patricio", "Paula Castro", "fim", null, null, null};
int newLength = names.length;
for(int i = 0; i < names.length; i++) {
if("fim".equals(names[i])) {
newLength = i;
break;
}
}
String[] truncated = java.util.Arrays.copyOf(names, newLength);
System.out.println(java.util.Arrays.toString(truncated));
Try it online here.

As per the Question's understanding Problem statement is as follows
Given a master array of String we need to return another array which contains the elements of master with null elements and element with value "fim" removed.
There can be null elements in between and not neccessary in the last and same for the element "fim"
Basic Algorithm
iterate master array
count the number of null & fim elements, create copy array of size =
master array size - null elements count
Check if the element is null if not null then add to copy array
public String[] removeNullNFimElementsFromArray(String[] master) {
int nullNFimCount = 0;
int masterSize = master.length;
for(int i = 0; i < masterSize; i++) {
if(master[i] == null || "fim".equals(master[i])) {
nullNFimCount++;
}
}
int copySize = masterSize - nullNFimCount;
String[] copyArray = new String[copySize];
for(int i = 0, j = 0; i < masterSize; i++) {
if(master[i] != null && !"fim".equals(master[i])) {
copyArray[j] = master[i];
j++;
}
}
return copyArray;
}

Related

Removing a String from a ragged 2D String array and shortening the array in the process

My professor gave out a review question for our midterm this week that I'm confused on:
Write a method that is given a two-dimensional (ragged) array of
String objects and returns a two-dimensional (ragged) array of String
objects where all the null entries have been removed. For example,
if the original array has the data (NULL represents a null
reference):
{"John", null, "Mary", "George", null},{null, "Pete", "Rick"},{null, null, null}};
the result generated by your method will be a two-dimensional
array with three rows.
{"John", "Mary", "George"},{"Pete", "Rick"},{}}; // last row will be empty
The code I have is:
public static String[][] removeNull2D(String[][] ragged) {
int counter = 0;
int nullCounter = 0;
String[][] array; // isn't initialized
// doesn't work I tested in debugger, need a way to shorten each row by the amount of null values it has
for (int i = 0; i < ragged.length; i++) {
for (int j = 0; j < ragged[i].length; j++) {
if (ragged[i][j] == null) {
nullCounter++;
for (j = 0; j < ragged[i].length; j++) {
array = new String[ragged.length][ragged[i].length - nullCounter];
}
}
}
}
// based off 1D array approach
for (int i = 0; i < ragged.length; i++) {
for (int j = 0; j < ragged[i].length; j++) {
if (ragged[i][j] != null) {
array[i][counter++] = ragged[i][j];
}
}
}
return ragged;
}
I understand I need to count the amount of null values in each row and subtract that from the total length of each row for the String array "array" (bad name I know). I thought maybe if I made a method for a 1D array, it would help me understand the logic a little better:
public static String[] removeNull1D(String[] a) {
String[] array = new String[a.length - 1];
int counter = 0;
for (int i = 0; i < a.length; i++) {
if (a[i] != null) {
array[counter++] = a[i];
}
}
a = array;
return array;
}
Still confused how the logic applies to the 2D ragged array method, any clarification would be appreciated! Also, I don't believe I can import anything (are not supposed to at least), and once again this is just a review question, so I'm not stressing about getting an answer, just trying to understand the logic behind it.
You could try it like this:
public static void main(String[] args) {
String[][] ragged = { { "John", null, "Mary", "George", null }, { null, "Pete", "Rick" }, { null, null, null } };
String[][] cleaned = new String[ragged.length][];
for (int i = 0; i < ragged.length; i++) {
cleaned[i] = clean(ragged[i]); // Apply clean method to each sub array.
}
System.out.println(Arrays.deepToString(cleaned));
}
private static String[] clean(String[] dirty) {
int nonNullCount = 0;
for (String string : dirty) {
if (string != null) {
nonNullCount++; // Count non-null Strings.
}
}
String[] clean = new String[nonNullCount]; // Create array for non-null Strings.
int cleanIndex = 0;
for (String string : dirty) {
if (string != null) {
clean[cleanIndex] = string; // Insert only non-null String at index.
cleanIndex++; // Only then update index.
}
}
return clean;
}
Seems a little bit inelegant to me, but at the moment I can't think of a way to prevent the double loop in clean(String[] dirty)
Nevertheless, it outputs [[John, Mary, George], [Pete, Rick], []] as desired.
Edit: Updated some commentary.

How to shift each elements in array using loops?

I want to shift each elements in array to left if there is a null. E.g
public static void main(String[] args) {
String asd[] = new String[5];
asd[0] = "zero";
asd[1] = "one";
asd[2] = null;
asd[3] = "three";
asd[4] = "four;
I want the output to be
zero, one, three, four.
The length should also be adjusted
How can i do this using loops? I tried using if statements to check if an element is not null copy that value to another array. But i dont know how to copy if there is a null.
Given the kind of question, I suppose you want a simple, loop only and array only based solution, to understand how it works.
You have to iterate on the array, keeping an index of the new insertion point. At the end, using that same index, you can "shrink" the array (actually copy to a new smaller array).
String[] arr = {"a","b",null,"c",null,"d"};
// This will move all elements "up" when nulls are found
int p = 0;
for (int i = 0; i < arr.length; i++) {
if (arr[i] == null) continue;
arr[p] = arr[i];
p++;
}
// This will copy to a new smaller array
String[] newArr = new String[p];
System.arraycopy(arr,0,newArr,0,p);
Just tested this code.
EDIT :
Regarding the possibility of shrinking the array without using System.arraycopy, unfortunately in Java arrays size must be declared when they are instantiated, and can't be changed (nor made bigger nor smaller) after.
So if you have an array of length 6, and find 2 nulls, you have no way of shrinking it to a length of 4, if not creating a new empty array and then copying elements.
Lists can grow and shrink, and are more handy to use. For example, the same code with a list would be :
String[] arr = {"a","b",null,"c",null,"d"};
List<String> list = new ArrayList<>(Arrays.asList(arr));
Iterator<String> iter = list.iterator();
while (iter.hasNext()) if (iter.next() == null) iter.remove();
System.out.println(list);
Try:
int lengthNoNull = 0;
for(String a : asd) {
if(a != null) {
lengthNoNull++;
}
}
String[] newAsd = new String[lengthNoNull];
int i = 0;
for(String a : asd) {
if(a != null) {
newAsd[i++] = a;
}
}
Piece of code using only arrays.
String[] x = {"1","2","3",null,"4","5","6",null,"7","8","9"};
String[] a = new String[x.length];
int i = 0;
for(String s : x) {
if(s != null) a[i++] = s;
}
String[] arr = Arrays.copyOf(a, i);
Or this:
String[] xx = {"1","2","3",null,"4","5","6",null,"7","8","9"};
int pos = 0, i = 0;
String tmp;
for(String s : xx) {
if(s == null) {
tmp = xx[pos];
xx[pos] = s;
xx[i] = tmp;
pos++;
}
i++;
}
String[] arr = Arrays.copyOfRange(xx, pos, xx.length);

Comparing two rows in a single 2D array

I am trying to compare two rows that are in different order from a 2D array, and store elements that are the same from both rows. Here's an example of what I have produced:
String[] row1 = new String[10];
String[] row2 = new String[10];
String[][] fruit = {{"apple", "banana", "kiwi"},{"kiwi", "oranges", "grapes"}};
for (int i = 0; i < fruit.length; i++ ) {
for (int j = 0; j < fruit[i].length; j++){
if(fruit[0][j].equals(fruit[1][j])) {
row1[j] = fruit[0][j];
row2[j] = fruit[1][j];
System.out.println("Match found");
}else{
System.out.println("Not found");
}
}
}
System.out.println("row1");
System.out.println(Arrays.deepToString(row1));
System.out.println("row2");
System.out.println(Arrays.deepToString(row2));
I want the row1[] and row2[] to store the elements that are the same (which is kiwi in this example). However, the problem is .equals function only detects matching patterns. The example above only prints out nulls from row1 and row2.
It should really print out:
row1
[kiwi]
row2
[kiwi]
Note: I don't want to declare... String check = "kiwi"; because the user can enter anything in the 2D array.
Any suggestions? I feel I am getting close. I saw a similar example of someone using .equals and that worked, but it was only for single arrays.
The limits of your for-loops have been messed up, as well as the array elements that you accessed for comparison. I guess you wanted something like this...
import java.util.Arrays;
public class RowCompare
{
public static void main(String[] args)
{
String[] row1 = new String[10];
String[] row2 = new String[10];
String[][] fruit = {{"apple", "banana", "kiwi"},{"kiwi", "oranges", "grapes"}};
for (int i = 0; i < fruit[0].length; i++ ) {
for (int j = 0; j < fruit[1].length; j++){
if(fruit[0][i].equals(fruit[1][j])) {
row1[i] = fruit[0][i];
row2[j] = fruit[1][j];
System.out.println("Match found");
}else{
System.out.println("Not found");
}
}
}
System.out.println("row1");
System.out.println(Arrays.deepToString(row1));
System.out.println("row2");
System.out.println(Arrays.deepToString(row2));
}
}
But you should probably describe what you want to do with the results. These fixed-size result arrays (String[10]) look dubious, and the currently sketched code can not easily be generalized for MORE than 2 rows. There is probably a MUCH more elegant solution using Sets and Lists ....
You're logic is slightly wrong in your loop.
If you look you are comparing
fruit[0][0].equals(fruit[1][0])
then
fruit[0][1].equals(fruit[1][1])
change if statement to
if(fruit[0][i].equals(fruit[1][j])) {
Your solution is very uneffective since you don't take advantage of the optimization algorythms like hashing:
You should use a HashSet or a HashMap to find fastly if an element is contained.
In addition collections have ready methods like retainAll() to keep only the existing elements (HashSet implements Collection so it's a good candidate for your needs)
retainAll: Retains only the elements in this collection that are contained in the
specified collection (optional operation)
HashSet row1 = new HashSet();
row1.add("Kiwi");
...
HashSet row2 = new HashSet();
row2.add...
System.out.println( row1.retainAll(row2) );
It is less confusing to put the sub-arrays into temporary (1D) arrays: row1Temp and row2Temp.
import java.util.Arrays;
/**
<P>{#code java DoubleArrayXmpl}</P>
**/
public class DoubleArrayXmpl {
public static final void main(String[] igno_red) {
String[] row1Output = new String[10];
String[] row2Output = new String[10];
String[][] fruit = {{"apple", "banana", "kiwi"},{"kiwi", "oranges", "grapes"}};
String[] row1Temp = fruit[0];
String[] row2Temp = fruit[1];
for(int i = 0; i < row1Temp.length; i++) {
for(int j = 0; j < row2Temp.length; j++) {
if(row1Temp[i].equals(row2Temp[j])) {
System.out.println("Match found");
row1Output[i] = row1Temp[i];
row2Output[j] = row2Temp[j];
}else{
System.out.println("Not found");
}
}
}
System.out.println("row1Output");
System.out.println(Arrays.deepToString(row1Output));
System.out.println("row2Output");
System.out.println(Arrays.deepToString(row2Output));
}
}
Output:
[C:\java_code\]java DoubleArrayXmpl
Not found
Not found
Not found
Not found
Not found
Not found
Match found
Not found
Not found
row1Output
[null, null, kiwi, null, null, null, null, null, null, null]
row2Output
[kiwi, null, null, null, null, null, null, null, null, null]
I don't know your requirements, but It's a little odd to put these duplicate values into two different arrays, let alone leaving so many values null. How about using an ArrayList to store a single copy of the matched fruit?
import java.util.Arrays;
/**
<P>{#code java DoubleArrayXmpl}</P>
**/
public class DoubleArrayXmpl {
public static final void main(String[] igno_red) {
ArrayList<String> alMatches = new ArrayList<String>(3);
String[][] fruit = {{"apple", "banana", "kiwi"},{"kiwi", "oranges", "grapes"}};
String[] row1Temp = fruit[0];
String[] row2Temp = fruit[1];
for(int i = 0; i < row1Temp.length; i++) {
for(int j = 0; j < row2Temp.length; j++) {
if(row1Temp[i].equals(row2Temp[j])) {
System.out.println("Match found");
alMatches.add(row1Temp[i]);
}else{
System.out.println("Not found");
}
}
}
System.out.println("All matched fruits:");
for(String s : alMatches) {
System.out.println(s);
}
}
}
Output:
Not found
Not found
Not found
Not found
Not found
Not found
Match found
Not found
Not found
All matched fruits:
kiwi
Or even better, just store the indexes of the matches:
import java.util.Arrays;
import java.util.ArrayList;
/**
<P>{#code java DoubleArrayToMatchedIdxListXmpl}</P>
**/
public class DoubleArrayToMatchedIdxListXmpl {
public static final void main(String[] igno_red) {
ArrayList<Integer> alMatchIdxsInRow1 = new ArrayList<Integer>(3);
String[][] fruit = {{"apple", "banana", "kiwi"},{"kiwi", "oranges", "grapes"}};
String[] row1Temp = fruit[0];
String[] row2Temp = fruit[1];
for(int i = 0; i < row1Temp.length; i++) {
for(int j = 0; j < row2Temp.length; j++) {
if(row1Temp[i].equals(row2Temp[j])) {
System.out.println("Match found");
alMatchIdxsInRow1.add(i);
}else{
System.out.println("Not found");
}
}
}
System.out.println("All matched fruits:");
for(int i : alMatchIdxsInRow1) {
System.out.println(fruit[0][i]);
}
}
}
Output:
Not found
Not found
Not found
Not found
Not found
Not found
Match found
Not found
Not found
All matched fruits:
kiwi

Remove Null array values

I am building an array based off comparing two other arrays. But when I initalize my third array I have to set the length. But that is making my array have null objects in some instances. Is there away I can drop the empty/null postions in the array. See my code so far below:
private String[] tags = new String[] { "Mike", "Bob", "Tom", "Greg" };
private boolean[] selected = new boolean[tags.length];
public String[] selected_tags = new String[tags.length];
for (int i = 0; i < tags.length; i++) {
if (selected[i] == true){
selected_tags[i] = tags[i];
}
}
I left out the code for the checkboxes that builds the Boolen selected [].
Either way if I only select 2 tags then my selected_tags[] array will be Mike, Bob, Null, Null
I need to get the Null Null out. Thanks in advance!
You can use ArrayList, instead of array.
private String[] tags = new String[] { "Mike", "Bob", "Tom", "Greg" };
private boolean[] selected = new boolean[tags.length];
public List<String> selected_tags = new ArrayList<String>();
for (int i = 0; i < tags.length; i++) {
if (selected[i] == true){
selected_tags.add(tags[i]);
}
}
No, you can't drop the null values (and change the length of the array) after you've created it. You'll have to create a new one (or for instance use an ArrayList as illustrated below):
List<String> list = new ArrayList<String>();
for (int i = 0; i < tags.length; i++)
if (selected[i] == true)
list.add(tags[i]);
// Convert it to an array if needed:
selected_tags = list.toArray(new String[list.size()]);
As others have mentioned, this is much easier with an ArrayList. You can even get a regular array from it with the toArray function.
Without using ArrayList, you would have to figure out the length first and not include the null values. As you can see, that's a little messy:
int length = 0;
for( boolean b : selected ) if(b) ++length; // Count the "true"s
String[] selected_tags = new String[length];
for( int i = 0, j = 0; i < tags.length; i++ )
if( selected[i] )
selected_tags[j++] = tags[i];
Instead of using a standard Java array, you should use an ArrayList : it'll allow you to add elements to it, automatically growing the list as needed.
Basically, you'd first declare / instanciate the ArrayList, without specifying any kind of size :
public ArrayList<String> selected_tags = new ArrayList<String>();
And, then, in your loop, you'd use the add() method to add items to that ArrayList :
selected_tags.add(tags[i]);

Remove Null Value from String array in java

How to remove null value from String array in java?
String[] firstArray = {"test1","","test2","test4",""};
I need the "firstArray" without null ( empty) values like this
String[] firstArray = {"test1","test2","test4"};
If you want to avoid fencepost errors and avoid moving and deleting items in an array, here is a somewhat verbose solution that uses List:
import java.util.ArrayList;
import java.util.List;
public class RemoveNullValue {
public static void main( String args[] ) {
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()]);
}
}
Added null to show the difference between an empty String instance ("") and null.
Since this answer is around 4.5 years old, I'm adding a Java 8 example:
import java.util.Arrays;
import java.util.stream.Collectors;
public class RemoveNullValue {
public static void main( String args[] ) {
String[] firstArray = {"test1", "", "test2", "test4", "", null};
firstArray = Arrays.stream(firstArray)
.filter(s -> (s != null && s.length() > 0))
.toArray(String[]::new);
}
}
It seems no one has mentioned about using nonNull method which also can be used with streams in Java 8 to remove null (but not empty) as:
String[] origArray = {"Apple", "", "Cat", "Dog", "", null};
String[] cleanedArray = Arrays.stream(firstArray).filter(Objects::nonNull).toArray(String[]::new);
System.out.println(Arrays.toString(origArray));
System.out.println(Arrays.toString(cleanedArray));
And the output is:
[Apple, , Cat, Dog, , null]
[Apple, , Cat, Dog, ]
If we want to incorporate empty also then we can define a utility method (in class Utils(say)):
public static boolean isEmpty(String string) {
return (string != null && string.isEmpty());
}
And then use it to filter the items as:
Arrays.stream(firstArray).filter(Utils::isEmpty).toArray(String[]::new);
I believe Apache common also provides a utility method StringUtils.isNotEmpty which can also be used.
If you actually want to add/remove items from an array, may I suggest a List instead?
String[] firstArray = {"test1","","test2","test4",""};
ArrayList<String> list = new ArrayList<String>();
for (String s : firstArray)
if (!s.equals(""))
list.add(s);
Then, if you really need to put that back into an array:
firstArray = list.toArray(new String[list.size()]);
Using Google's guava library
String[] firstArray = {"test1","","test2","test4","",null};
Iterable<String> st=Iterables.filter(Arrays.asList(firstArray),new Predicate<String>() {
#Override
public boolean apply(String arg0) {
if(arg0==null) //avoid null strings
return false;
if(arg0.length()==0) //avoid empty strings
return false;
return true; // else true
}
});
This is the code that I use to remove null values from an array which does not use array lists.
String[] array = {"abc", "def", null, "g", null}; // Your array
String[] refinedArray = new String[array.length]; // A temporary placeholder array
int count = -1;
for(String s : array) {
if(s != null) { // Skips over null values. Add "|| "".equals(s)" if you want to exclude empty strings
refinedArray[++count] = s; // Increments count and sets a value in the refined array
}
}
// Returns an array with the same data but refits it to a new length
array = Arrays.copyOf(refinedArray, count + 1);
Quite similar approve as already posted above. However it's easier to read.
/**
* Remove all empty spaces from array a string array
* #param arr array
* #return array without ""
*/
public static String[] removeAllEmpty(String[] arr) {
if (arr == null)
return arr;
String[] result = new String[arr.length];
int amountOfValidStrings = 0;
for (int i = 0; i < arr.length; i++) {
if (!arr[i].equals(""))
result[amountOfValidStrings++] = arr[i];
}
result = Arrays.copyOf(result, amountOfValidStrings);
return result;
}
A gc-friendly piece of code:
public static<X> X[] arrayOfNotNull(X[] array) {
for (int p=0, N=array.length; p<N; ++p) {
if (array[p] == null) {
int m=p; for (int i=p+1; i<N; ++i) if (array[i]!=null) ++m;
X[] res = Arrays.copyOf(array, m);
for (int i=p+1; i<N; ++i) if (array[i]!=null) res[p++] = array[i];
return res;
}
}
return array;
}
It returns the original array if it contains no nulls. It does not modify the original array.
Those are zero-length strings, not null. But if you want to remove them:
firstArray[0] refers to the first element
firstArray[1] refers to the second element
You can move the second into the first thusly:
firstArray[0] = firstArray[1]
If you were to do this for elements [1,2], then [2,3], etc. you would eventually shift the entire contents of the array to the left, eliminating element 0. Can you see how that would apply?

Categories