In my application I need to have a 2 dimensional array. If I define it fix it works fine, like this:
static final String arrGroupelements[] = {"India", "Australia", "England", "South Africa"};
static final String arrChildelements[][] = { {"Sachin Tendulkar", "Raina", "Dhoni", "Yuvi" },
{"Ponting", "Adam Gilchrist", "Michael Clarke"},
{"Andrew Strauss", "kevin Peterson", "Nasser Hussain"},
{"Graeme Smith", "AB de villiers", "Jacques Kallis"} };
However, in my code I have two lists. the first is list of recipe name that i can get it.
LinkedList<String> recipeList = dbShoppingHandler.getAllRecipeNames();
String arrGroupelements[] = new String[recipeList.size()];
for(int i=0; i<recipeList.size(); i++) {
arrGroupelements[i] = recipeList.get(i);
}
My second list is list of ingredients. In order to get list of ingredients i need to set recipe name and then i can get the list. However, i don't know how put this list as second dimension. my code is like this:
String arrChildelements[][] = new String[recipeList.size()][20];
for(int i=0; i<recipeList.size(); i++) {
LinkedList<String> ingredient = dbShoppingHandler.getIngredientsOfRecipeName(recipeList.get(i));
for(int j=0; j<ingredient.size(); j++) {
arrChildelements[i][j] = ingredient.get(j);
}
}
Bad thing is, i need to set a number (in my case 20) for second dimension. If i do like this for lists that have 5 items i will have 15 " " elements and those have more than 20 items the code ignore them.
First dimension is fix but i need to adjust second dimension based on number of ingredients.
any suggestion are appreciated. thanks.
How about assigning an array in the desired sise:
String arrChildelements[][] = new String[recipeList.size()][];
// not mentioning second dimension size ^^
for(int i=0; i<recipeList.size(); i++) {
LinkedList<String> ingredient = dbShoppingHandler.getIngredientsOfRecipeName(recipeList.get(i));
arrChildelements[i] = String[ingredient.size()];
// assigning new array here ^^
for(int j=0; j<ingredient.size(); j++) {
arrChildelements[i][j] = ingredient.get(j);
}
}
I suggest not to use 2D arrays for dynamic structures. Arrays are immutable, so you have to copy them, create gaps and move elements around. The standard Java library doesn't offer many useful methods to do that.
Instead, use a list of lists:
List<List<String>> data = new ArrayList<List<String>>();
Lists have many useful methods to append elements, insert and remove them and they will make you life much easier.
The simplest way to to not assume you know the length in advance.
String[][] arrChildelements[] = new String[recipeList.size()][];
for(int i=0; i<recipeList.size(); i++) {
List<String> ingredient = dbShoppingHandler.getIngredientsOfRecipeName(recipeList.get(i));
arrChildelements[i] = ingredient.toArray(new String[0]);
}
Related
Background:
I am working on a scraping project using Selenium that gets data from tables on webpages in our Test and Production environments and then stores the data into two separate Array List of String type (one for test/prod). The data are numbers (double) and there are 3 columns and anywhere from 13-16 rows of data. It varies because I am pulling data from over 145 countries and each table is different.
Please not that that this is just an example. The code that I present here is not the Selenium Script I am running.
Issue:
The issue lies when I am trying to convert the data from the two Array Lists that I have into two 2 dimensional arrays. I have worked with very basic 2d arrays before, but only created them off of user input.
Based on the research I have done before, the syntax for converting an ArrayList to an array is:
ArrayList<String> b = new ArrayList<>();
b.add("1.50");
b.add("3.12");
b.add("5.25%");
b.add("2.16");
b.add("4.36");
b.add("7.76%")
//This is just a snippet, remember the list would have anywhere from 13-16
indices.
String[] x = b.toArray();
But how do I convert that same list into an 2 dimensional array in the format of
1.50 3.12 5.25%
2.16 4.36 7.76%
starting a new line every third index?
You have to loop the List and add the items to a new one unless you find value with a percentage (%) in it. Then, you create a new List. This solution is based on the % character appearance, not the fixed size of a gap between elements to split which might be an advantage.
List<List<String>> outer = new ArrayList<>();
List<String> inner = new ArrayList<>();
for (String s: b) {
inner.add(s);
if (s.contains("%")) {
outer.add(inner);
inner = new ArrayList<>();
}
}
The List<List<String>> outer will contain these values:
[[1.50, 3.12, 5.25%], [2.16, 4.36, 7.76%]]
To convert the structure from List<List<String>> to String[][], you can use java-stream or a simple for-loop approach iterating and filling the array.
String[][] array = outer.stream()
.map(a -> a.stream().toArray(String[]::new)) // List<String> to String[]
.toArray(String[][]::new); // List<String[]> to String[][]
A typical for loop should do:
List<List<String>> accumulator = new ArrayList<>();
for (int i = 0; i < b.size(); i+=3) {
List<String> temp = new ArrayList<>(b.subList(i, i + 3));
accumulator.add(temp);
}
accumulator now looks like:
[[1.50, 3.12, 5.25%], [2.16, 4.36, 7.76%]]
note that the above assumes you'll always a list that is a multiple of three, if that it not the case then you can handle it as follows:
List<List<String>> accumulator = new ArrayList<>();
for (int i = 0; i < b.size(); i+=3) {
List<String> temp = b.stream().skip(i).limit(3).collect(toList());
accumulator.add(temp);
}
if you strictly require the result to be a String[][] then you can get it as follows:
String[][] strings =
accumulator.stream()
.map(l -> l.toArray(new String[0]))
.toArray(String[][]::new);
You can iterate over your list an add the entries manually in an 2d-array:
String[][] array = new String[b.size()/3][3];
for (int i = 0; i < b.size(); i++) {
int row = i / 3;
int col = i % 3;
array[row][col] = b.get(i);
}
System.out.println(Arrays.deepToString(array));
I have two arrays :
String[] dishes = {"Dish1", "Dish2", "Dish3", "Dish4", "Dish5", "Dish6"};
String[] dishCategory = {"daily Dish", "daily Dish", "daily Dish", "side Dish", "side Dish", "Dish special"};
As result I want two Arrays: one with the daily dishes and the dish special in it, and the other one only with the side dishes.
That's why I tried to get the "side Dish" index of the dishCategory to delete these Strings of my dishes Array. But I even couldn't work out a function to get all the "side dish" indexes.
Does anyone know a good solution?
The easiest way to do this to create 2 new arrays.
List<String> dailyAndSpecialList = new ArrayList<>();
List<String> sideList = new ArrayList<>();
for (int i = 0; i < dishCategory.length; i++) {
if (dishCategory[i].equals("side Dish")) {
sideList.add(dishes[i]);
} else {
dailyAndSpecialList.add(dishes[i]);
}
}
String[] sideArray = sideList.toArray(new String[sideList.size()]);
String[] dailyAndSpecialArray = dailyAndSpecialList.toArray(new String[dailyAndSpecialList.size()]);
You could iterate through the dishCategory array and compare the element of array with your "side dish" and store the matching index in other Arraylist and later on using these index , you can remove or do whatever you want to do.
sample code :-
ArrayList<Integer> sideDishIdx = new ArrayList<>();
int i=0;
for(String s : dishCategory){
if(s.equalsIgnoreCase("side Dish"))
sideDishIdx.add(i);
i++;
}
for(Integer idx : sideDishIdx){
System.out.println("idx "+idx);
}
I have the following code which sorts a mixed array of items while maintaining the position of types:
For example:
[20, "abc", "moose", 2,1] turns into [1, "abc", "moose", 2, 20]
Algorithm:
public class Algorithm {
public static String[] sortMixedArray(String[] input){
if (input.length == 0){
return input;
}
// make new arraylist for strings and numbers respectively
List<String> strs = new ArrayList<String>();
List<Integer> numbers = new ArrayList<Integer>();
// add values to the arraylist they belong to
for (String item : input){
if (NumberUtils.isNumber(item)){
numbers.add(Integer.valueOf(item));
} else {
strs.add(item);
}
}
// sort for O(nlogn)
Collections.sort(strs);
Collections.sort(numbers);
// reuse original array
for (int i = 0; i < input.length; i++){
if (NumberUtils.isNumber(input[i])) {
input[i] = String.valueOf(numbers.remove(0));
} else {
input[i] = strs.remove(0);
}
}
return input;
}
public static void main(String[] args) {
String[] test = new String[] {"moo", "boo"};
System.out.println(Arrays.toString(sortMixedArray(test)));
}
I have a two-part question:
1. Is switching between array and arraylist efficient? That is, should I have used arrays everywhere instead of arraylist if my input MUST be an array.
2. What is the best way to place arraylist items back into a array? I am checking for type, is there a better way?
1.If you do it the way you have it in your code then it's perfectly fine. If you know beforehand how many elements you will have it's better to use arrays but thats not the case in your example.
2.The best and easiest way is to use the toArray() function of the List interface.
ArrayList<String> list = ...;
String[] array = list.toArray(new String[list.size()]);
But this won't work for your code since you are merging two lists into one array. You can still improve your code a bit because you do not actually have to remove the items from the lists when putting them back in the array. This safes some computation since removing the first element from an ArrayList is very inefficient (O(N) runtime per remove operation).
for (int i = 0, s = 0, n = 0; i < input.length; i++) {
if (NumberUtils.isNumber(input[i])) {
input[i] = Integer.toString(numbers.get(n++));
} else {
input[i] = strs.get(s++);
}
}
No but it highly unlikely to matter unless you have a million of elements.
Do whatever you believe is simplest and most efficient for you, the developer.
BTW the least efficient operations is remove(0) which is O(N) so you might change that.
I have a situation like
String[] ids = new String[depts.size()];
for (int i=0; i<ids.length; i++)
{
ids [i] = ("Dept" + .... )
}
So the loop looks at ids whose length is set to depts.size. But I need to add another string item to ids [i] like a "Region" + reg_num. Like the next item in ids[i] must be "Region" + reg_num and this is repeated for every department.
Since it is controlled by length, how do I do that? How do I adjust the loop to take 1 additional item. Any suggestions will be appreciated.
Thanks.
Just use a List instead of an array. Unlike arrays, lists are dynamically resizable:
final List<String> newList = new ArrayList<>(oldList);
newList.add(newElement);
EDIT if you are still using Java 6 you'll have to:
final List<String> newList = new ArrayList<String>(oldList);
instead
EDIT 2 depending on your use case, you may not even need a second list; as lists are dynamically resizable, unless you absolutely need to copy it, just keep the same list:
// first call
list.add(something);
// second call
list.add(somethingElse);
// etc etc
Without seeing more of the code however, it's hard to tell.
If you know before hand then initialize the array accordingly and add the elements as:
String[] ids = new String[depts.size()+1];//added one in the length
for (int i=0; i<ids.length; i++)
{
ids [i] = ("Dept" + .... )
}
ids[ids.length-1] = "Region"+....;
or
String[] ids = new String[2*depts.size()];//added one in the length
for (int i=0; i<ids.length; i=i+2)
{
ids [i] = ("Dept" + .... )
ids[i+1] = "Region"+....;
}
If you are trying to store a department for each id then its better to define a custom class like this:
public class Region {
String id;
String dept;
public Region(String id, String dept) {
this.id=id;
this.dept=dept;
}
// getters for id and dept
}
then define your region array like this
Region[] regions = new Region[depts.size()];
for (int i=0; i<regions.length; i++) {
regions[i] = new Region("Dept"+i, "Region"+i);
}
If I understand your reqs correctly, you can do something like this (but remember that you can hold a list of strings instead of an array, to change it dynamically):
String[] ids = new String[depts.size()*2];
for (int i=0; i<ids.length; i+=2)
{
// depts index would be i/2
ids [i] = ("Dept" + .... )
ids[i+1] = "Region"; // + ...
}
Vector<String> totalProducts = Products.getProductNames();
Vector<String> selectedProducts = Products.getSelectedProductNames();
The selectedProducts vector is a subvector of totalProducts (meaning that selectedProducts contains one, more or all of the elements from totalProducts). What I want is to combine these two vectors and make a single JList, which contains all the elements from totalProducts, and with the elements of selectedProducts already selected.
What I tried:
Vector<Integer> indices = new Vector<Integer>();
JList prdList = new JList(totalProducts);
for(int i = 0; i < totalProducts.size(); i++)
{
for(String name : selectedProducts)
{
if(totalProducts.contains(name)) indices.add(i);
}
}
Object [] objIndices = indices.toArray();
//... Cast from Object [] to int [] ....
prdList.setSelectedIndices(intIndices);
...but this selects all the elements in the final JList.
Previously I tried:
JList prdList = new JList(totalProducts);
for(String tName : totalProducts)
{
for(String sName : selectedProducts)
{
if(totalProducts.contains(sName)) prdList.setSelectedValue(sName, false);
}
}
...but this one selected only the last element from the selectedProducts.
Can you please help me to do it right?
Your attempt that selects all items does so because you're iterating over each item, and if any item from the selectedProducts list is in the total list, adds the iteration item's index to the final selection list. Try changing your loop to something like this:
for(int i = 0; i < totalProducts.size(); i++)
{
String name = totalProducts.get(i);
if(selectedProducts.contains(name)) indices.add(i);
}
in debugging your first attempt (which looks like it should work, what was the contents of your intIndices array? because that looks like it should work, presuming your array conversion works.
however, since selectedproducts is guaranteed to be less items than total, you might want to iterate over that instead?
List<Integer> indices = new ArrayList<Integer>(selectedProducts.size());
for(String name : selectedProducts)
{
int index = totalProducts.indexOf(name);
if (index != -1)
indices.add(index);
}
although, since indexOf is a linear search through a list, it probably doesn't make much of a difference either way.
as for your second attempt, the ListSelectionModel has methods for adding a selected index (addSelectionInterval(int index0, int index1))
, you're using the one that sets (overwrites) the selection.
see http://download.oracle.com/javase/6/docs/api/javax/swing/ListSelectionModel.html
aside: you might want to use List<> instead of Vector<>, as vector has a lot of unecessary synchronization overhead. Unless you need the synchronization....
edit fixed copy+paste of add(i) with add(index)