2D Array but with indexing - java - java

I'm looping into a number of rows and trying to filter these rows with some if statements. within each if statement I need to have an index for a number of elements. I could have done that using 2d String[][] but the problem is I don't know what is the size of each row at this stage.
I'm looking to store my data like the following :
0 1 3 4 5 6 7 etc..
0 str str str str str str str
1 str str str
2
3 str str str str str str
Any suggestion would be appreciate it
Edit:
Sorry if my question wasn't clear. But I'll explain it more here.
My Loop looks like this:
newArrayList
for (i; i < List ;i++)
{
if(...)
{
newArrayList.add.(0, List.get(i));
} else if(...)
{
newArrayList.add.(2, List.get(i));
} else if(...)
{
newArrayList.add.(6, List.get(i));
}
}
The above code doesn't work but I'm just trying to explain what I need to do actually! My if statements can occur several times and I would like to consider an index for each if statement expectation plus a set of strings. Thanks.

You could try an ArrayList of ArrayList's:
ArrayList<ArrayList<String>> strings = new ArrayList<ArrayList<String>>();
strings.add(new ArrayList<String>()); // Adding a first array to the 'array of arrays'
strings.get(0).add("String1"); // Add a string to the first array,
// Similar to: arr[0][0] = "String1"
//To access them element by element use a double for, note that "s" is each element
for (ArrayList<String> l : strings) {
for (String s : l) {
}
}
PS: An ArrayList<Object> is like an array Object[] but more flexible. It has some useful methods like:
arr_list.get(index); // Getting an object in position 'index'
arr_list.add(object); // Adding an element (Similar to assignment in arrays)
Edit
If you know the number of "rows" then you have to add them to the array of arrays. With this for you are "creating the empty rows of your array":
Rows:
0
1
...
n
for (int i = 0; i < n; i++) { // n is the number of "rows"
strings.add(new ArrayList<String>());
}
Then add an element to a "row":
strings.get(0).add("String1"); // get(0) to obtain the first row, get(1) to obtain the second...

If your index is consecutive form 0 to n and you are inserting them in that order, but n is not known in advance: There are two classical solution:
1) If you do it with a pre-allocated fixed array, you obviously need two passes. The first pass is scanning the row and counting the elements. The second pass is then creating the index.
2) You can do it with a collection allowing dynamic growth via an .add(item) method, like List
If you will convert the collection to an fixed size array later, then it is maybe faster to use method 1) since the add method may be slower due to memory management / allocation / re-allocation.
If your index is consecutive form 0 to n and n is known in advance, but you are inserting the elements not in that order:
You should use solution 1) above.
If your index is not consecutive and n is known known in advance:
3) You create a Map<Integer,String> strings and add the elements via strings.put(index, string) (in any order).
If your index is not unique (as we have finally found out):
4) You crate a Map<Integer,ArrayList<String>> stringMap and add elements via
addStringForIndex(String string, Integer index)
{
listForString = stringMap.get(index);
if(listForString == null) {
listForString = new ArrayList<String>;
map.put(index, listForString);
}
listForString.add(string);
}

If you don't know the size of your array, you could use a List implementation, for example:
ArrayList<ArrayList<String>> 2D = new ArrayList<ArrayList<String>>();
And then use a for-each loop

Related

Java: Removing an empty Element from String Array [duplicate]

This question already has answers here:
Resize an Array while keeping current elements in Java?
(12 answers)
Closed 3 years ago.
I have an array String ar[] = {"HalloWelt", " "};, ar.length is 2.
It does register two values within "HalloWelt" on index 0, and a blank/empty string on index 1;
I wonder how can I remove empty space on the index 1 - > but also keep it as a String Array since it is necessary for next task. Or how to do bunch of conversions but end up with String Array in the end.
My attempt
public String[] arraysWhiteSpaceEliminator(String[] arr) {
int k=0; //Identify how big the array should be i.e. till it reaches an empty index.
for(int i=0; i<bsp.length;i++) {
arr[i].trim();
System.out.println(arr[i].isEmpty());
if(arr[i].isEmpty()) {
}
else {
k = k+1; //if the index isn't empty == +1;
}
}
String[] clearnArray = new String[k];
for(int s = 0; s<k; s++) {
clearnArray [s] = arr[s]; //define New Array till we reach the empty index.
//System.out.println(clearnArray [s]+" " +s);
}
return clearnArray ;
};
The logic is very simple:
Identify how big the clearnArray should be.
Iterate through original Array with .trim() to remove white Space and check wether isEmpty().
Add to the k if the index isnt Empty.
Create clearnArray with the k as size.
Loop through originial Array till k -> add all the items to cleanArray till k.
Issue: .trim() and .isEmpty() don't record that the index is empty. ?!
A solution with streams:
String[] clean = Arrays.stream(ar)
.map(String::trim)
.filter(Predicate.isEqual("").negate())
.toArray(String[]::new);
Note that this assumes none of the array elements are null. If this is a possibility, simply add the following stage before the map:
.filter(Objects::nonNull)
The problem with your code is that after counting to find k, you just write the first k elements from the original array. To solve the problem by your technique, you need to check each element of the input array again to see if it's empty (after trimming), and only write to the new array the elements which pass the test.
The code can be simplified using the "enhanced" for loop, since you don't need indices for the original array. (The variable i keeps track of the current index in the new array.) Note also that strings are immutable, so calling .trim() does nothing if you don't use the result anywhere. Your code also refers to bsp which is not defined, so I changed that.
int k = 0;
for(String s : arr) {
s = s.trim();
if(!s.isEmpty()) {
k++;
}
}
String[] cleanArray = new String[k];
int i = 0;
for(String s : arr) {
s = s.trim();
if(!s.isEmpty()) {
cleanArray[i] = s;
i++;
}
}
return cleanArray;
Calculate the number of non-null elements and create an array of that size, like
String[] strs = ...;
int count = 0;
for (int i = 0; i < strs.length; i++) {
if (strs[i] != null) count++;
}
String newStrArray[] = new String[count];
int idx = 0;
for (int i = 0; i < strs.length; i++) {
if (strs[i] != null) newStrArray[idx++] = strs[i];
}
return newStrArray;
You could also probably make this prettier using streams. However I haven't used streaming functionality in Java, so I can't help there.
Two things to note:
Unless you are serializing or the nulls are causing other problems, trimming the array just to get rid of the nulls probably won't have an impact on memory, as the size of an array entry (4 bytes) is very likely inconsequential to the memory block size allocated for the Array object
Converting first to an List and then back to an array is lazy and possibly inefficient. ArrayList, for example, will likely include extra space in the array it creates internally so that you can add more elements to the ArrayList and not have to create a whole new internal array.
in your method, create a new
List cleanedList = new ArrayList();
add iterate through ar[]ar[] = ["HalloWelt",""], and add only non-empty values to cleaned List....then return the array.
return cleanedList.toArray()
like below:
List<String> cleanedList = new ArrayList<>();
for(String s : arr) {
s = s.trim();
if(!s.isEmpty()) {
cleanedList.add(s);
}
}
return cleanArray.toArray();

Simplest way to add an item between items in a List

What is the simplest way to add an item between all items in a List?
For example, a List of Strings
{"1", "2", "3"}
becomes
{"1", ",", "2", "," "3"}
Edit 1
My first naive attempt which crashed and burned HARD (don't do this):
for (int i=0; i < list.size(); i++) {
if(i==0) continue;
if(i==list.size()) continue;
list.add(i, new String(","));
}
You have a very functional way to think about your problem. Here is what I would do:
// use ArrayList, it is very easy to handle and comes with all necessary methods as Payam already said
ArrayList<String> list = new ArrayList<>();
list.add("1");
list.add("2");
list.add("3");
// this is the actual solution:
for (int i = 1; i < list.size(); i += 2) {
list.add(i, ",");
}
// and this is just for testing (printing) the list
for (String s : list) {
System.out.print("'"+s + "' ");
}
Expected outcome would be:
'1' ',' '2' ',' '3'
So, you loop through your list.
First: your index i starts at 1 (you don't want to add anything before the first element).
Then instead of incrementing your index by one (i++) you increment it by two (i+=2). That way your index points to every even position in the list.
At last you want to use add(index, value) to add a new value (here: ,) to the list at the specified position. Adding a new value to position any position will shift the following elements of your list "one to the left". They will not be overwritten (only moved to another index) and you can still loop your list from the beginning to the end, since you don't care if it grows in size or not.
Why don't you just use an ArrayList it's way easier to add and remove items.
Adding:
ArrayList<Integer> arrlist = null;
arrlist.add(0, 2);
....
Removing:
arrlist.remove(index);

Parse a string, create single strings and compare them to a value in an if statement?

I'm trying to do something that might seem simple do you but I'm kind of stuck and I can't wrap my head around how to do it.
So basically what I want to do is parse string str and create smaller strings and compare them to something in an if statement
String str = ("1, 2, 3);
StringTokenizer st = new StringTokenizer(str, ",");
while (st.hasMoreElements()){
//instead of printing the element I want to generate str[i] or something of the sort
System.out.print(st.nextElemenet());
}
//then I want to do this as many times as I have str[i]
if(str1 == 2 || str2 == 3 || str3 == 3){
//do something
}
Basically I want to parse a string, generate a bunch of smaller strings and use them in an if statement. Any ideas? Sorry if it seems like a simple question but I'm kind of stuck lol
PS Java 1.4 doesn't support .split and it needs to be in java 1.4 ^_^
I can make an ArrayList but I'm still not sure how to iterate through it in the if, comparing all the values of it with a given value. :/
I think what you require is a String array.
String[] strArray = new String[st.countTokens()]; // Create an array with no. of tokens as the size
int counter = 0; // Counter variable to be used as the arrays index.
while (st.hasMoreElements()){
//instead of printing the element I want to generate str[i] or something of the sort
strArray[counter++] = st.nextElement(); // add the element to the array
}
This way you can add all the tokens to a String array and then you can traverse through this array and compare the elements. Now to do some if-checks on each of those elements you need a loop. I used the standard for loop since you're using Java 1.4.
for(int i=0; i<strArray.length; i++) {
if(strArray[i].equals("someString")) { // use equals method for string value comparisons.
// do something
}
}

How to get 2D array possible combinations

I have the following 2D array:
String[M][]
String[0]
"1","2","3"
String[1]
"A", "B"
.
.
.
String[M-1]
"!"
All the possible combinations should be in store in a resulting array
String[] combinations. So for example:
combinations[0] == {"1A....!")
combinations[1] == {"2A....!")
combinations[2] == {"3A....!")
combinations[3] == {"1B....!")
Notice that that the arrays are of variable length. Order of the elements in the output String doesn't matter. I also don't care if there are duplicates.
If the arrays were the same length, nested loops would do the trick, but they are not, and I really don't know how to approach the problem.
You can iterate through the combinations one at a time like clockwork by using an array to record the size of each inner array, and a counter array which keeps track of which member to use from each inner array. Something like this method:
/**
* Produce a List<String> which contains every combination which can be
* made by taking one String from each inner String array within the
* provided two-dimensional String array.
* #param twoDimStringArray a two-dimensional String array which contains
* String arrays of variable length.
* #return a List which contains every String which can be formed by taking
* one String from each String array within the specified two-dimensional
* array.
*/
public static List<String> combinations(String[][] twoDimStringArray) {
// keep track of the size of each inner String array
int sizeArray[] = new int[twoDimStringArray.length];
// keep track of the index of each inner String array which will be used
// to make the next combination
int counterArray[] = new int[twoDimStringArray.length];
// Discover the size of each inner array and populate sizeArray.
// Also calculate the total number of combinations possible using the
// inner String array sizes.
int totalCombinationCount = 1;
for(int i = 0; i < twoDimStringArray.length; ++i) {
sizeArray[i] = twoDimStringArray[i].length;
totalCombinationCount *= twoDimStringArray[i].length;
}
// Store the combinations in a List of String objects
List<String> combinationList = new ArrayList<String>(totalCombinationCount);
StringBuilder sb; // more efficient than String for concatenation
for (int countdown = totalCombinationCount; countdown > 0; --countdown) {
// Run through the inner arrays, grabbing the member from the index
// specified by the counterArray for each inner array, and build a
// combination string.
sb = new StringBuilder();
for(int i = 0; i < twoDimStringArray.length; ++i) {
sb.append(twoDimStringArray[i][counterArray[i]]);
}
combinationList.add(sb.toString()); // add new combination to list
// Now we need to increment the counterArray so that the next
// combination is taken on the next iteration of this loop.
for(int incIndex = twoDimStringArray.length - 1; incIndex >= 0; --incIndex) {
if(counterArray[incIndex] + 1 < sizeArray[incIndex]) {
++counterArray[incIndex];
// None of the indices of higher significance need to be
// incremented, so jump out of this for loop at this point.
break;
}
// The index at this position is at its max value, so zero it
// and continue this loop to increment the index which is more
// significant than this one.
counterArray[incIndex] = 0;
}
}
return combinationList;
}
How the method works
If you imagine the counter array being like a digital clock reading then the first String combination sees the counter array at all zeroes, so that the first String is made by taken the zero element (first member) of each inner array.
To get the next combination the counter array is incremented by one. So the least-significant counter index is increased by one. If this causes its value to become equal to the length of the inner array it represents then the index is zeroed, and the next index of greater significance is increased. A separate size array stores the length of each inner array, so that the counter array loop knows when an index has reached its maximum.
For example, if the size array was:
[3][3][2][1]
and the counter array was at:
[0][2][1][0]
then the increment would make the least significant (right-most) index equal to 1, which is its maximum value. So that index gets zeroed and the next index of greater significance (the second-from-right) gets increased to 2. But that is also the maximum of that index, so it gets zeroed and we move to the next index of greater significance. That gets increased to three, which is its maximum value so it gets zeroed and we move to the most significant (left-most) index. That gets increased to 1, which is less than its maximum so the incremented counter array becomes:
[1][0][0][0]
Which means the next String combination is made by taking the second member of the first inner array, and the first member of the next three inner arrays.
Dire warnings and notes
I wrote this just now in about forty minutes, and it's half-one in the morning, which means that even though it seems to do exactly what is needed, there are very likely bugs or bits of code which could be optimised. So be sure to unit test it thoroughly if its performance is critical.
Note that it returns a List rather than a String array because I think that Java Collections are vastly preferable to using arrays in most cases. Also, if you need a result set with no duplicates, you can simply change the List to a Set which will automatically drop duplicates and leave you with a unique set.
If you really need the result as a String array, don't forget you can use the List<String>.toArray(String[]) method to simply convert the returned List to what you need.
This problem has a very nice recursive structure to it (which also means it could explode in memory, the correct way should be using iterators such as the other answer, but this solution looks nicer imo and we can prove correctness inductively because of the recursive nature). A combination consists of an element from the first list attached to all possible combinations formed from the remaining (n-1) lists. The recursive work is done in AllCombinationsHelper, but you invoke AllCombinations. Note to test for empty lists and more extensively.
public static List<String> AllCombinations(List<List<Character>> aList) {
if(aList.size() == 0) { return new ArrayList<String>(); }
List<Character> myFirstSubList = aList.remove(0);
List<String> myStrings = new ArrayList<String>();
for(Character c : myFirstSubList) {
myStrings.add(c.toString());
}
return AllCombinationsHelper(aList, myStrings);
}
public static List<String> AllCombinationsHelper(List<List<Character>> aList,
List<String> aCollection) {
if(aList.size() == 0) { return aCollection; }
List<Character> myFirstList = aList.remove(0);
List<String> myReturnSet = new ArrayList<String>();
for(String s : aCollection) {
for(Character c : myFirstList) {
myReturnSet.add(c + s);
}
}
return AllCombinationsHelper(aList, myReturnSet);
}
Should be straight forward to do with recursion.
Let me rephrase a bit, so the terminology is less confusing.
We will call String[] as Token List, which is a list of Tokens
Now you have a List of Token List, you want to get one Token from each Token List available, and find out all combination.
What you need to do is, given a list of TokenList
If the List is having only one TokenList, the content of the Token List itself is all combinations
Else, make a sub-list by excluding the first Token List, and find out all combinations of that sub list. When you have the combinations, the answer is simply loop through your first token list, and generate all combinations using each token in the token list, and the result combinations.
I am only giving a psuedo code:
List<String> allCombinations(List<TokenList> listOfTokenList) {
if (length of strings == 1) {
return strings[0];
}
List<String> subListCombinations
= allCombination(listOfTokenList.subList(1)); // sublist from index 1 to the end
List<String> result;
for each (token in listOfTokenList[0]) {
for each (s in subListCombination) {
result.add(token + s);
}
}
return result;
}
I have been struggling with this problem for some time. But I finally solved it. My main obstacle was the SCOPE I used for declaring each variable. If you do not declare your variables in the correct scope, then the variable will retain changes made in the previous iteration.
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class RecursiveAlgorithmTest {
private static int recursiveCallsCounter = 0;
public static ArrayList<ArrayList<String>> testCases = new ArrayList<ArrayList<String>>();
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
//set values for ArrayOfArrays
ArrayList<String> VariableA = new ArrayList<String>(Arrays.asList("red", "green"));
ArrayList<String> VariableB = new ArrayList<String>(Arrays.asList("A", "B", "C"));
ArrayList<String> VariableC = new ArrayList<String>(Arrays.asList("1", "2", "3", "4"));
ArrayList<ArrayList<String>> AofA = new ArrayList<ArrayList<String>>();
AofA.add(VariableA); AofA.add(VariableB); AofA.add(VariableC);
System.out.println("Array of Arrays: ToString(): " +AofA.toString());
ArrayList<String> optionsList = new ArrayList<String>();
//recursive call
recurse(optionsList, AofA, 0);
for (int i = 0 ; i < testCases.size() ; i++) {
System.out.println("Test Case " + (i+1) + ": " + testCases.get(i));
}
}//end main(String args[])
private static void recurse(ArrayList<String> newOptionsList,
ArrayList<ArrayList<String>> newAofA, int placeHolder){
recursiveCallsCounter++;
System.out.println("\n\tStart of Recursive Call: " + recursiveCallsCounter);
System.out.println("\tOptionsList: " + newOptionsList.toString());
System.out.println("\tAofA: " + newAofA.toString());
System.out.println("\tPlaceHolder: "+ placeHolder);
//check to see if we are at the end of all TestAspects
if(placeHolder < newAofA.size()){
//remove the first item in the ArrayOfArrays
ArrayList<String> currentAspectsOptions = newAofA.get(placeHolder);
//iterate through the popped off options
for (int i=0 ; i<currentAspectsOptions.size();i++){
ArrayList<String> newOptions = new ArrayList<String>();
//add all the passed in options to the new object to pass on
for (int j=0 ; j < newOptionsList.size();j++) {
newOptions.add(newOptionsList.get(j));
}
newOptions.add(currentAspectsOptions.get(i));
int newPlaceHolder = placeHolder + 1;
recurse(newOptions,newAofA, newPlaceHolder);
}
} else { // no more arrays to pop off
ArrayList<String> newTestCase = new ArrayList<String>();
for (int i=0; i < newOptionsList.size();i++){
newTestCase.add(newOptionsList.get(i));
}
System.out.println("\t### Adding: "+newTestCase.toString());
testCases.add(newTestCase);
}
}//end recursive helper
}// end of test class
In Python one uses itertools.product and argument unpacking (apply)
>>> import itertools
>>> S=[['1','2','3'],['A','B'],['!']]
>>> ["".join(x) for x in itertools.product(*S)]
['1A!', '1B!', '2A!', '2B!', '3A!', '3B!']

How to remove strings of certain lengths

So I have this array, and I want to delete strings that are 2 or 4 characters in length (strings that contain 2 or 4 characters). I am doing this method, and it doesn't work, even though logically, it SHOULD work.
public static void main(String[] args)
{
ArrayList<String> list = new ArrayList<String>();
list.add("This");
list.add("is");
list.add("a");
list.add("test");
for (int i=0; i<list.size(); i++)
{
if(list.get(i).length()==2 || list.get(i).length()==4)
{
list.remove(i);
}
}
}
I'd like to stick to this method of doing it. Can you please give me some suggestions as to how to correct this code?
The output of this code when I run it is:
[is, a]
Even though I want the output to be
[a]
because "is" is 2 characters long.
The list is changing. Iterate from last element to first or use iterator.
PeterPeiGuo is right - you are removing elements which is shifting your index.
This is a prime candidate for an iterator.
Iterator<String> it = list.iterator();
while(it.hasNext()) {
String val = it.next();
if(val.length() == 4 || val.length() == 2) {
it.remove();
}
}
Another option for it:
When you remove one, decrease your index by 1.
By the way, it works, but is not a good coding style.
for (int i=0; i<list.size(); i++)
{
if(list.get(i).length()==2 || list.get(i).length()==4)
{
list.remove(i);
i--;
}
}
Deleting things from the list changes the indexes of the remaining things in the list.
When your code runs, in the first iteration, i is 0 and it deletes the "this" entry at 0.
On the second iteration i is 1 and thus it doesn't check the value at 0, which is now "is" because the "this" was removed.
As PeterPeiGui says in his answer, you can work around it in this particular case just by going backward, but traversing a collection and mutating it simultaneously always has a risk of introducing plenty of confusion.

Categories