Remove null elements from String array where "All elements are null" - java

I am tasked with fixing a problem where this code returns string values but because the iterations add null elements it needs to trim or remove those. During debug the value of the array contains mostly "All elements are null", but other solutions like data.removeAll(Collections.singleton(null)); do not work because it is the elements that are null and it still returns as the original size. Is there a way to remove these elements after the iterations of the initial loop or should this be done inside the loop where data is assigned the "value"?
Code:
private String[][] getStringsFromSpreadSheet(Sheet ws) {
int rowNum = ws.getLastRowNum() + 1;
int colNum = ws.getRow(0).getLastCellNum();
String[][] data = new String[(rowNum - 1)][colNum];
int k = 0;
for (int i = 1; i < rowNum; i++) {
ws.getRow(i);
if (ws.getRow(i) != null) {
for (int j = 0; j < colNum; j++) {
if (ws.getRow(i).getCell(j) != null) {
String value = ws.getRow(i).getCell(j).toString();
if (!value.toString().isEmpty()) {
data[k][j] = value;
}
}
}
}
k++;
}
return data;
}

You can easily trim out null values from a List, but you've been trying to convert your array to a List incorrectly.
Since you've got a two-dimensional array, you need to create a nested list (List<List<String>>) to store the data.
For instance, let's start with a mostly empty String[][]:
String[][] data = new String[3][3];
data[0][0] = "foo";
data[1][1] = "bar";
//data is a 3x3 array
for (int i=0; i<data.length; i++) {
System.out.println(Arrays.toString(data[i]));
}
//[foo, null, null]
//[null, bar, null]
//[null, null, null]
We can take each sub-array, convert it to a list, trim it, and then add the non-empty lists to an enclosing list, like so:
List<List<String>> dataList = new ArrayList<>();
for (int i=0; i<data.length; i++) {
List<String> temp = new ArrayList<>();
Collections.addAll(temp, data[i]);
temp.removeAll(Collections.singleton(null));
if (!temp.isEmpty()) {
dataList.add(temp);
}
}
We can then convert the list back to a String[][], which will be "trimmed" of null data, like so:
String[][] newData = new String[dataList.size()][];
for (int i=0; i<dataList.size(); i++) {
List<String> subList = dataList.get(i);
newData[i] = subList.toArray(new String[subList.size()]);
}
//newData is a 2x1 array
for (int i=0; i<newData.length; i++) {
System.out.println(Arrays.toString(newData[i]));
}
//[foo]
//[bar]

All you need to do is set it to blank string. check the else clause.
private String[][] getStringsFromSpreadSheet(Sheet ws) {
int rowNum = ws.getLastRowNum() + 1;
int colNum = ws.getRow(0).getLastCellNum();
String[][] data = new String[(rowNum - 1)][colNum];
int k = 0;
for (int i = 1; i < rowNum; i++) {
ws.getRow(i);
if (ws.getRow(i) != null) {
for (int j = 0; j < colNum; j++) {
if (ws.getRow(i).getCell(j) != null) {
String value = ws.getRow(i).getCell(j).toString();
if (!value.toString().isEmpty()) {
data[k][j] = value;
}
} else {
data[k][j] = "";
}
}
}
k++;
}
return data;
Now the data would not have any null values but it may have blank / empty strings.

Based on your comments it seems that you have to return a String[][] for getStringsFromSpreadSheet. Is this correct? If so there is not a nice way to keep track of how many cells are null/not null. 2D arrays have to be rectangular. So if one of your rows has 3 columns populated and one row only has 1 column populated, the array has to be at least 3 columns wide. I have tried to represent this visually below.
Row | Column 1 | Column 2 | Column 3 |
1 | something | something | something |
2 | something | null | null |
So for the above data you have to declare a 2D array at least 2x3 to fit all of your data. No matter what, if one of your rows does not populate all 3 columns, you will always have a null cell for that row. Array.length will always return the size of the array, never the count of how many are null/not null.
Your options are limited if you can only return a String[][]. If you are able to return something else, we can work through some options.

Related

Remove items from custom arraylist implemetation without .remove

I'm working on a custom ArrayList implementation and I have one method where I'm trying to remove an item per conditions from an array such as E[] elements. The array is initialized by doing something like this:
String[] contents = {"chicken", "hippo", "goat"};
ArrayI<String> newarray = new ArrayI(contents);
newarray.chooser(new LongChooser());
It should remove words length 4 or less and return an array like this:
["chicken", "hippo"]
I'm trying not to use any built in methods, like remove(), clone(), arraycopy(), etc. I can't seem to get this to work, I've tried creating a duplicate array and trying to copy elements over like this:
E[] copy = (E[]) (new Object[this.size-1]);
for (int i = 0; i < size; i++) {
if (shorter) {
copy[i] = elements[i];
}
else {
for (int j = i; j<this.size-1; j++) {
elements[j] = elements[j+1];
}
elements[size-1] = null;
size -= 1;
}
for (int i =0; i< copy.length; i++) {
elements[i] = copy[i];
}
size -= 1;
I know this is not the correct way because they aren't the same size array and just returns [longword, longerword, null]. Also I'm pretty sure I should be using the size variable, but it doesn't seem to do much.
How do I get this to work? Thanks.
Create an array to hold the [filtered] results. Its initial size is zero.
Iterate through contents.
If the current element of contents needs to be retained, then
create a temporary array whose length is one greater than the array that holds the results.
copy the results array to the temporary array
set the last element of the temporary array to the current element of contents
assign the temporary array to the results array
Here is the code, using only simple arrays. I presume you can adapt it to your needs. Note that the last line is simply to check the value of newContents. It is not required.
String[] contents = {"chicken", "hippo", "goat"};
String[] newContents = new String[0];
for (String str : contents) {
if (str.length() > 4) {
String[] temp = new String[newContents.length + 1];
for (int i = 0; i < newContents.length; i++) {
temp[i] = newContents[i];
}
temp[newContents.length] = str;
newContents = temp;
}
}
System.out.println(Arrays.toString(newContents));

How to store data in a string array using java collection

I have stored data in a List<String[]> and need to store those data into an another String array using a loop. I have created a String array (value) and stored data in there but the issue is first element is getting replaced by second inside the loop and it will show only the last element at the end of the loop.
CSVReader reader = new CSVReader(new FileReader(csvfile));
List<String[]> data = reader.readAll();
String[] values = new String[5];
for (int i = 1; i < 5; i++) {
values = data.get(i);
System.out.println(values[1]); // data is getting replaced here
}
System.out.println(values[1]); // this will show only the last stored value
Lists are 0 indexed so unless you intentionally want to skip the first element then don't start the loop iteration at 1 rather at 0.
Yes, when performing the last println after the loop only data related to the last String[] is shown because at each iteration you're updating values i.e. values = data.get(i); to store the current String[] hence the aforementioned outcome.
You probably want a String[][] as opposed to String[] because each String[] represents a line of the file.
Thus, assuming you only want to get the first five lines from data you can do it as:
String[][] lines = data.subList(0, 5).toArray(String[][]::new);
or for all the lines read:
String[][] lines = reader.readAll().toArray(String[][]::new);
and you can test it with:
System.out.println(Arrays.deepToString(lines));
// generating data
List<String[]> data =
Stream.iterate(0, n -> n + 1)
.limit(10)
.map(i -> new String[]{"a" + i, "b" + i, "c" + i, "d" + i, "e" + i, "f" + i})
.collect(Collectors.toList());
String[][] values = new String[data.size()][];
// copy the data
for (int i = 0; i < data.size(); i++)
{
values[i] = data.get(i).clone();
}
//print the result
Arrays.stream(values).map(Arrays::toString).forEach(System.out::println);
Replace :
for (int i = 1; i < 5; i++) {
values = data.get(i);
System.out.println(values[1]); // data is getting replaced here}
With:
for (int i = 0; i < 5; i++) {
values = data.get(i);
System.out.println(values[1]); // data is getting replaced here}
I think you have a little error inside the for loop. Try this:
CSVReader reader = new CSVReader(new FileReader(csvfile));
List<String[]> data = reader.readAll();
String[] values = new String[5];
for (int i = 1; i < 5; i++) {
values[i] = data.get(i);
System.out.println(values[1]); // data is getting replaced here
}
System.out.println(values[1]); // this will show only the last stored value
I think you are missing the "[i]" at the first line inside the for loop.
Your data variable contains a list of String[] (string arrays). Your for loop is attempting to store them in values which is a single String[].
Depending on what you are trying to do, you can do as the comments suggest and make a 2D String array. However, the fact that you want to remove them from a perfectly good list of String[]'s leads me to believe you probably want them in one big String[].
Below is an example of how to put the first N (in this case 5) words you parse from the csv into the values variable. However, we would be able to give you better guidance if you provided what the ultimate use case of your code snippet is.
// initialize test data
List<String[]> data = new ArrayList<String[]>();
String[] a = {"a1", "a2"};
String[] b = {"b1", "b2"};
String[] c = {"c1", "c2"};
data.add(a);
data.add(b);
data.add(c);
// big N is how many words you want
int N = 5;
// little n tracks how many words have been collected
int n = 0;
String[] values = new String[N];
// loop through csv collect
for (int i = 0; i < data.size(); i++){
String[] cur = data.get(i);
// loop through the strings in each list entry
for (int j = 0; j < cur.length; j++){
// store value and increment counter
values[n] = cur[j];
n++;
// stop if maximum words have been reached
if (n >= N)
break;
}
// stop if maximum words have been reached
if (n >= N)
break;
}
for (int i = 0; i < values.length; i++)
System.out.println(values[i]);

How to put strings into a matrix?

I'm having trouble with this, maybe you could help me:
I have 3 strings like: word1, word2, word3 and I have to build a matrix with them, like this:
on the first row : word1("ABC"), second row: word2("DEF") and third row: word3("GHI").
A|B|C
D|E|F
G|H|I
I need this because after that I have to check if the formed words ("ADG","BEH","CFI") are in an array of words. And I don't know how to put those strings in the matrix so I can check. Any help is useful.
Thanks
Based on this comment:
the words have the same size, because the matrix is actually like a puzzle. I choose randomly 3 words from an array, put them in a matrix and check after that if the words resulted are from the same array.
I'll assume some things in order to make this work (since we don't have enough info):
You have an array of Strings where you have all the words
private String[] words;
You have a method to randomly pick up 3 Strings from this array.
private String s1, s2, s3;
public void pickThreeRandomWords() {
s1 = aRandomWord(words);
s2 = aRandomWord(words);
s3 = aRandomWord(words);
//or maybe another fancy algorithm to get this...
}
So you would need an array of array of chars based on these 3 Strings. This code could do the work for you:
public char[][] createMatrixFromStrings(String s1, String s2, String s3) {
char[][] theMatrix = new char[3][]; //yes, hardcoded
theMatrix[0] = s1.toCharArray();
theMatrix[1] = s2.toCharArray();
theMatrix[2] = s3.toCharArray();
return theMatrix;
}
Of course, if you would want to make this method to support more than 3 Strings you can make the method to receive a random quantity of Strings:
public char[][] createMatrixFromStrings(String ... strings) {
if (strings == null || strings.length == 0) return null;
char[][] theMatrix = new char[strings.length][];
int i = 0;
for(String s : strings) {
theMatrix[i++] = s.toCharArray();
}
return theMatrix;
}
You can build the result words without a matrix:
List<String> verticalWords = new ArrayList<String>();
for (int i = 0; i < horizontalLen; i++){
String currentWord = "";
for (int j = 0; j < wordCount; j++)
currentWord += words.get(j).get(i);
verticalWords.add(currentWord);
}
P.S. For the currentWord you can use a StringBuilder to make it more efficient, but I doubt it is highly needed here.
Java doesn't have matrix.It has array of array
So,you can try this
List<char[]> lst=new ArrayList();//stores a list of char[]
lst.add(("ADC".toCharArray()));//adds array of characters i.e 'A','D','C'
lst.add(("DEF".toCharArray()));
lst.get(0)[0];//A
lst.get(1)[0];//D
Now you can iterate vertically
for(int i=0;i<lst.size();i++)temp+=lst.get(i)[0];
temp would have AD which you can now cross check with equals method
The main thrust of this goal is that you're taking a one-dimensional value, and converting it into a two-dimensional value. There are many ways you can do this, but here are the two that come off the top of my head:
Set up a nested while loop to iterate over the first dimension, and when it reaches the length, reset and cause the outer loop to increment, much like a clock
You can create a new subarray using ArrayUtils.toSubArray(), and with some finagling, get that to work:
Create a new row of the array each time, based on the dimension slices you want to hit up. I'll leave figuring this one out as an exercise for the reader. But here's a hint:
for(int i = 0; i < theDimension; i++, j += 3) {
ret[i] = ArrayUtils.subarray(word, i*theDimension, j);
}
Lastly, I assume that there's a restraint on the type of input you can receive. The matrix must be square, so I enforce that restriction before we build the array.
I strongly encourage you to poke and prod this answer, and not just blindly copy it into your schoolwork. Understand what it's doing so you can reproduce it when you're asked to again in the future.
public char[][] toMatrix(int theDimension, String theEntireWord) {
if(theEntireWord.length() != theDimension * theDimension) {
throw new IllegalArgumentException("impossible to add string to matrix of uneven dimension");
}
char[][] ret = new char[theDimension][theDimension];
int i = 0;
int j = 0;
while(i < theDimension) {
if(j == theDimension) {
j = 0;
++i;
} else {
ret[i][j] = theEntireWord.charAt((i * theDimension) + j);
j++;
}
}
return ret;
}
I think this will sort your problem.
package printing;
public class Matrix {
public static void main(String[] args) {
//Length can define as you wish
String[] max = new String[10];
String[] out = null;
//Your Inputs
max[0]="ADG";
max[1]="BEH";
max[2]="CFI";
//following for loop iterate your inputs
for (int i = 0; i < max.length; i++) {
if(out==null){out= new String[max.length];}
String string = max[i];
if(string==null){ break;}
//Here breaking input(words) one by one into letters for later contcatnating.
String[] row = string.split("");
for (int j = 0; j < row.length; j++) {
String string1 = row[j];
// System.out.println(string1);
//create the values for rows
if(out[j]!=null){ out[j]=out[j]+string1;}
else{
out[j]=string1;
}
}
}
//following for loop will out put your matrix.
for (int i = 0; i < out.length; i++) {
String string = out[i];
if(out[i]==null){break;}
System.out.println(out[i]);
}
}
}

First Element in TwoDimensional Array goes to null?

I am using this code to insert the details in to TwoDimensional Array. But while retrieving the data from the array the first element value changes to null.
Cursor consultancy = db.getConsultancy(this);
if(consultancy!=null)
{
consultancy.moveToFirst();
consultancy.moveToNext();
consultancynames = new String[(int) db.getConsultancyCount()-1];
for(int i=0;i<db.getConsultancyCount()-1;i++)
{
consultancynames[i] = consultancy.getString(2);
int consultantid = Integer.parseInt(consultancy.getString(consultancy.getColumnIndex(TimeAndExpensesLocalDB.CT_CONSULTANCYID)));
Cursor project_namecur = db.getProjectCode(this, consultantid);
if(project_namecur!=null)
{
project_namecur.moveToFirst();
projectname = new String[(int) db.getConsultancyCount()][project_namecur.getCount()];
for(int j=0;j<project_namecur.getCount();j++)
{
projectname[i][j] = project_namecur.getString(3);
project_namecur.moveToNext();
}
}
consultancy.moveToNext();
}
}
//... Print array
for (int i =0; i < consultancynames.length; i++) {
for (int j = 0; j < projectname.length; j++) {
System.out.print(" " + projectname[i][j]);
}
System.out.println("");
}
Output
05-25 12:58:22.700: I/System.out(2373): null null null
05-25 12:58:22.700: I/System.out(2373): Other-1 Other-2 Other-3
I am not sure what is happening.
Thanks for your help guys..
You're creating a new array on each iteration of the loop:
projectname = new String[(int) db.getConsultancyCount()][project_namecur.getCount()];
So on the first iteration you're creating an array and filling in the first "row" of the array. On the second iteration you're creating a new array (which will default to having null elements) and filling in the second row.
I suspect you need to allocate the "outer" array once before the loop, then allocate the "inner" array based on how many project names there are for that consultant:
// Note: more idiomatic names would be consultancyNames and
// projectNames. It's also unclear why you're subtracting one from the count...
consultancynames = new String[(int) db.getConsultancyCount() - 1];
projectnames = new String[consultancynames.length][];
for (int i = 0;i< consultancenames.length; i++) {
...
projectnames[i] = new String[project_namecur.getCount())];
...
}
Then you'll need to change your display code too, e.g. to
for (int i =0; i < projectname.length; i++) {
for (int j = 0; j < projectname[i].length; j++) {
System.out.print(" " + projectname[i][j]);
}
System.out.println("");
}
Note that you can't do the following:
projectname = new String[(int) db.getConsultancyCount()][project_namecur.getCount()];
for(int j=0;j<project_namecur.getCount();j++)
{
projectname[i][j] = project_namecur.getString(3);
project_namecur.moveToNext();
}
Here's why:
After the first line projectname will be an array of arrays.
Since the arrays are object references you have an array of object references.
Since the default value of an object reference is null, you'll have an array of null elements.
This means you can't do
projectname[i][j] = project_namecur.getString(3);
since it corresponds to
String[] row = projectname[i];
// row == null !
row[j] = project_namecur.getString(3);

save get values using arrayList java

In my example, I try to get val(0) and val(1) each time.
After for loop I need to save my values to use them for other calculations:
String[] columns = { "col1" , "col2" };
String[] y = { "TEST", "BUG" ,"ENH" };
List<int[]> values = new ArrayList<int[]>();
for (int j = 0; j < y.length; j++) {
// do some actions
for(int[] v : values) {
//v is the array for one iteration, use it like this:
int col1 = v[0];
int col2 = v[1];
values .add(v);
}
}
System.out.prinln(values) =>gives : []
Out of for loop, my values are raised, how do can I do to get my values after for?
Thanks
I don't understand the question either, but, here's my best guess at interpreting what the question is trying to do:
String[] columns = {"col1" , "col2"};
String[] y = { "TEST", "BUG" ,"ENH"};
int[][] values = new int[y.length][columns.length]; // 2D array
for (int j = 0; j < y.length; j++) {
for (k = 0; k < columns.length; k++) {
values[j][k] = table.getVal(j, columns[k]);
}
}
for (int value : values) {
// do something with value
}
Without knowing the structure of 'table', your data in the int array 'values' should be readily accessible via a for loop:
for (int v: value) {
//use 'v' here
}
or directly:
values[0];
values[1];
...etc
However, it might simply be a language barrier here preventing us from understanding the true problem.
If you want to get the values of all iterations after the loop, you first have to provide a fitting data structure. An easy way might be to use a 2-dimensional array:
int[][] values = new int[y.length][columns.length];
However, I'd recommend using a collection instead (assuming the original values has to be an array):
List<int[]> values = new ArrayList<int[]>();
Then fill that in your loop, either using array index y or just adding a new array in each iteration.
After the loop you can then iterate over the result, like this:
for(int[] v : values) {
//v is the array for one iteration, use it like this:
int col1 = v[0];
int col2 = v[1];
//or like this
for(int value : v) {
//value is the value of one column in one iteration
}
}
UPDATE:
In your updated code you're not putting anything into the list.
Note that you still have to create an array per iteration, get the values from your source (IIRC it was named table) and put them into the array, then add the array to the list using values.add(...).
Also note that the loop I added above is meant to read the values later, it doesn't show you how to fill the list in the first place.

Categories