Dividing a Java List into sublists based on values - java

Here's my list:
myList =
["HEADING","POST","POST","POST","CALL_TO_ACTION","HEADING","POST","POST","POST","CALL_TO_ACTION","HEADING","POST","POST","CALL_TO_ACTION"]
I would like to have some logic in place that would help me divide myList into below three sub-lists (stored as, say, List<List<String> subLists):
["HEADING","POST","POST","POST","CALL_TO_ACTION"]
["HEADING","POST","POST","POST","CALL_TO_ACTION"]
["HEADING","POST","POST","CALL_TO_ACTION"]
Please note, the number three comes from the number of occurrences of the element "HEADING" (which I could find out using Collections.frequency(myList, "HEADING")).

One way to do this is,
Step 1: Collect all the indices from your myList where "HEADING" appears.
List<Integer> indexList = new ArrayList<>();
for(int index = 0; index < list.size(); index++) {
if(list.get(index).equals("HEADING"))
indexList.add(index);
}
Step 2: Iterate through this indexList and create sub lists by using current index and the next index.
for(int builderIndex = 0; builderIndex < indexList.size(); builderIndex++) {
List<String> test = null;
if(builderIndex == indexList.size() - 1) {
test = list.subList(indexList.get(builderIndex), list.size());
} else {
test = list.subList(indexList.get(builderIndex), indexList.get(builderIndex + 1));
}
System.out.println(test);
}
Boundary condition is to check if the current index is equal to one less than the size of the indexList. If yes, then the end index of the sub list would be the size of the original list.
I hope this helps.

Related

Java mapping data from two arrays and insert into third array

I am having difficulty mapping the data in two lists into a third list. My sample data is as follows:
Categorylist ID: 1,2,3,4,5,6,7,8,9,10,42,46,49,50
CurrentMonthByCat ID: 1,2,3,4,5,6,7,8,9,10,42,49,50
(the transaction amount value for CurrentMonthByCat: 92,46,40,180,60,10,1510,200,500,10,234,12)
There is a missing 46 in the currentMonthByCat. I am trying to do it in a way such that if the currentMonthByCat ID does not exist from the categorylist ID, I will insert 0 into the third list rather than getting the transaction amount from CurrentMonthByCat and push it into the third list.
ArrayList<Double> total = new ArrayList<Double>();
for(int i = 0; i < categorylist.size(); i++){
for(int j = 0; j < currentMonthByCat.size(); j++){
if(categorylist.get(i).getCategoryID().equals(currentMonthByCat.get(j).getCategory().getCategoryID())){
Log.d("IIIII", categorylist.get(i).getCategoryID());
Log.d("JJJJJ", currentMonthByCat.get(j).getCategory().getCategoryID());
total.add((double)currentMonthByCat.get(j).getTransactionAmt());
}else{
total.add(0.0);
}
}
}
for(int k = 0; k < total.size(); k++){
Log.d("KKKKK", String.valueOf(total.get(k)));
}
But the printed out result of total list is:
92,0,0,0,0,0,0,0,0,0,0,0,0,0,46,0,0,0...
What I expected is:
92,46,40,180,60,10,1510,200,500,10,0,234,12
I wanted to insert 0 only if the ID in currentMonthByCat does not match the ID in categorylist. For instance, the ID 46 which is the 3rd position from the right.
I realized the reason is because firstly I inserted 92 into third array, then the categorylist ID is still at 1, then it will compare with all the rest in the currentMonthByCat before moving to ID 2. That is why the unnecessary zeros. But I not sure how to actually sort it to achieve what I wanted.
Any ideas?
Thanks in advance.
It's easy one. you can't take a decision of adding zero or value in the total array unless the inner loop finish. so probably you add element existAtIndex and initialize it with -1 and in the loop if you find the element then assign the index to existAtIndex and break the loop or if it's not exist then you add zero. so the code will be something like :
ArrayList<Double> total = new ArrayList<Double>();
int existAtIndex;
for(int i = 0; i < categorylist.size(); i++){
// search for the element index
existAtIndex = -1;
for(int j = 0; j < currentMonthByCat.size(); j++){
if(categorylist.get(i).getCategoryID().equals(currentMonthByCat.get(j).getCategory().getCategoryID())){
existAtIndex = j;
break;
}
}
// add the value in the element index or add zero if the element not exist
if (existAtIndex != -1) {
total.add((double)currentMonthByCat.get(existAtIndex).getTransactionAmt());
}
else {
total.add(0.0);
}
}
for(int k = 0; k < total.size(); k++){
Log.d(String.valueOf(total.get(k)));
}
For better code you could use contains method to check for the item if exist or not in arrayList instead of using the basic loop. Good luck
You have a lot of code for what you are trying to do here. I think the following snippet does what you want in a very readable and maintainable way.
//First of all we are interested in getting a transaction amount for each value in currentMonthByCat
//so loop around using your object (not sure what it's called)
for(CurrentMonth value : currentMonthByCat){
//check if it's present.
//We create a new method here that gets you your category list as a list of integers.
//This is key to making the whole method much more readable.
if(categorylist.getIdsAsList().contains(value.getCategory().getCategoryID())){
//it is so add it
total.add(value.getTransactionAmt());
} else {
//it's not so add a 0
total.add(0.0);
}
}
The getIdsAsList method could look like this:
public List<Integer> getIdsAsList(){
List<Integer> result = new ArrayList<>();
for (CategoryListItem item : categorylist) {
result.add(item.getCategoryId());
}
return result;
}
Put your values into Map<Integer, Double>
Map<Integer, Double> map = new HashMap<Integer, Double>();
for (int i = 0; i < currentMonthByCat.size(); ++i) {
//... categoryId = currentMonthByCat.get(i).categoryId
//... amount = currentMonthByCat.get(i).amount
map.put(categoryId, amount);
}
Then traverse the map using values from Categorylist ID:
// create result arraylist
ArrayList<Double> total = new ArrayList<Double>();
for (int i = 0; i < categorylist.size(); ++i) {
Double amount = map.get(categorylist.get(i));
if (amount == null) {
total.add(0.0);
} else {
total.add(amount);
}
}
The result list total will contain amounts for existing mappings, or zeros for non-existent.
Other way
If it is guaranteed categorylist is sorted and CurrentMonthByCat is sorted
you can then traverse one of the lists while keeping index/cursor to the other list and not iterating the other list from the beginning, but from previously remembered cursor value, resulting in better average performance than n^2

Reversing and combining a list

I have the following list:
list 1= 1,2,3,4,5,6
I am trying to make a list that contains the following:
list c= 1,6,2,5,3,4
However, I cannot figure out how to do it. I know how to iterate through 6 but I don't know how to get to the last number and iterate backwards. I know a ListIterator can be used to go backwards but I still cannot figure it out.
This is what I did to add the original, I just don't understand how to iterate backwards:
public static void q(Set<String>list1)
{
Set<String>combined = new HashSet();
Iterator<String> forward = list1.iterator();
Iterator <String> backwards = list1.iterator();
for (int i=0; i<list1.size(); i++)
{
combined.add(forward.next());
//code to go backwards
}
}
This isn't to solve your problem, but rather to show you how ListIterator can be used to go backwards since you couldn't figure it out.
List<Integer> list = new ArrayList<>();
for (int n = 1; n <= 6; n++) { // Add 1, 2, ... 6 to list
list.add(n);
}
ListIterator it = list.listIterator(list.size());
while (it.hasPrevious()) {
System.out.println(it.previous());
}
The listIterator method of a List allows you to specify the index to start at as a parameter.
The hasPrevious method of the ListIterator checks if there is a previous element (self-explanitory).
The previous() method of the ListIterator returns the previous element in the list and moves the cursor position backwards.
Using ListIterator you can go forwards and backwards as you please using next() and previous() respectively.
Alternatively, using a for statement instead of using ListIterator...
for (int i = list.size() - 1; i >= 0; i--) {
System.out.println(list.get(i));
}
I am not sure if you really wanted a Set given you were talking about lists. This is the idea without explicitly using list iterators however they would behave the similarly.
How to use a list iterator: http://www.java2s.com/Tutorial/Java/0140__Collections/ListIteratorInreverseorder.htm
public static List<Integer> interleaveFrontBack(List<Integer> list) {
if (list.size() <= 2){
return new LinkedList<Integer>(list);
}
List interleaved = new LinkedList<Integer>();
int end = list.size() - 1;
int front = 0;
while (end > front){
interleaved.add(list.get(front++));
interleaved.add(list.get(end--));
}
// if odd sized list need to add last element
if (end == front){
interleaved.add(list.get(front));
}
return interleaved;
}
Simple Algo would be
1.) just use two positions , i =0 for increment and j = size-1 for decrements
2.) add elements to new list using i and j positions while traversing to the middle of the content list
Integer []aa=new Integer[]{1,2,3,4,5,6};
List<Integer> list =Arrays.asList(aa);
int n=list.size();
List<Integer> list2 =new ArrayList<>();
for (int i = 0,j=list.size()-1; i <n/2 ; i++,j--) {
list2.add(list.get(i));
list2.add(list.get(j));
}
// if(n%2!=0) list2.add(list.get(n/2)); // un-comment this , to handle
// odd list size too ,dynamism
list2.forEach(i->System.err.print(i+" "));
Output:
1 6 2 5 3 4
Assuming that you simply want to put the last element of the first list on the second index, you can do something like:
List<Integer> input = Arrays.asList(1, 2, 3, 4, 5, 6);
// create new list that initially contains first and last element of input list
List<Integer> output = new ArrayList<>(Arrays.asList(input.get(0), input.get(input.size()-1)));
// now iterate the "in between" input elements and add them to output
for (int i=1; i < input.size() -1 ; i++) {
output.add(input.get(i));
}
System.out.println("in: " + input);
System.out.println("out: " + output);
Of course, the above is just one way of doing this; there are many others
Not sure what your exactly looking for and where your code has broke. You could try:
List<Integer> intergers = new ArrayList<>();
for(int i = 1; i < 7; i++) {
if(i < 6) {
intergers.add((i-1), i);
} else {
intergers.add(1, i); //when i is 6 place it in the second index
}
}
System.out.println("List: " + intergers.toString());
With java list you can chose the index and if that index has a value the value well be pushed to the next index. It was the simplest thing I could think of. This is what it printed out:
List: [1, 6, 2, 3, 4, 5]

IndexOutOfBoundsException when working with arrayList

The task is described here Creating combination of numbers or here Permutations of integer array algorithm.
I decided to solve this problem in this way:
From first number to the last check the possibility of permutation:
Create arraLists of the first permutation and of the difference
del1 and rem0
Bool is an object with two parametrs: st - start and end
It`s new permutation
I create new Bool, that at the start have the same start and end, like it is one number. So, we cant use this number anymore before starting new permutation with another start number. And we remove it from the list of numbers rem . And start create permutation with checking.
for (int index = 0; index < arr.length; index++) {
List<Integer> del1 = new ArrayList<Integer>();
List<Integer> rem0 = new ArrayList<Integer>();
for (int i = 0; i < del.length; i++) {
del1.add(del[i]);
}
for (int i = 0; i < arr.length; i++) {
rem0.add(arr[i]);
}
Bool start = new Bool(arr[index], arr[index]);
rem0.remove(index);
check(start, del1, rem0);
}
Checking:
ucet - number of "good" permutations, if the difference of new permutation is the same, as the first, it is "good".
So, I for the ending number I add difference number and if it = number in the list of possible numbers - I add this number to the end of permutation, remove it from the list of possible and remove difference prom the list of differences(by creating new lists).
And then continue creating.
private static void check(Bool start, List<Integer> del2, List<Integer> rem) {
if (del2.isEmpty()) {
ucet++;
}
for (int index = 0; index<rem.size(); index++) {
for (int i = 0; i<del2.size(); i++) {
if(start.end+del2.get(i)==rem.get(index)){
List<Integer> del3 = new ArrayList<Integer>();
List<Integer> rem2 = new ArrayList<Integer>();
del3=del2;rem2=rem;
Bool con=new Bool(start.st,rem.get(index));
rem2.remove(index);
del3.remove(i);
check(con,del3,rem2);
}
}
}
}
But I have one bug, that I cant understand. Its IndexOutOfBoundsException. In the string if(start.end+del2.get(i)==rem.get(index)){ .
And it causes del2.get(i).
But the problem is, that i<del2.size().
Can you help me to deal with it? Thanks
You are removing entities from the list as you are looping through it, not good. You could try using while loop in conjunction with iterable.hasNext() or instead of rem0.remove(index) do rem0.set(index, null).

Check array list and remove some arguments [duplicate]

This question already has answers here:
Iterating through a Collection, avoiding ConcurrentModificationException when removing objects in a loop
(31 answers)
Closed 10 years ago.
I have array list of strings. I want to check in specific moment if in this array I have more elements than my "i", if yes I want to remove that elements. For example. I have five elements in array. I choose element which index is four. I want to check if exist higher element(in this case that higher will be element which index is 5) and remove that element. If I choose 3 element I want to remove 4 and 5 element. I do something like that:
for(int j = 0; j<descriptions.size();j++){
if(!descriptions.get(i+1).isEmpty()){
descriptions.remove(i+1);
}
}
This solution work good when I choose 3 element and two elements was removed. But when I want choose 4 element I get index out of bound exception. How I can solve my problem?
I don't quite see the point of using for loop in your code.
What you probably want to do is to remove any items beyond i th element in the list.
The easiest way to do is to repeatedly remove the last element from the list.
Here's a sample code for reference:
while(descriptions.size() > i){
descriptions.remove(descriptions.size()-1);
}
public static void main(String[] args) {
//list of string with 5 elements
List<String> descriptions = new ArrayList<String>();
descriptions.add("first");
descriptions.add("second");
descriptions.add("third");
descriptions.add("4");
descriptions.add("5");
//the size you want to check for the list
int i = 3;
int howMuchToRemove = descriptions.size()-i;
//if the list how more object from > i , we will remove objects from it
if (howMuchToRemove > 0)
for (int j=0 ; j < howMuchToRemove ; j++)
//remove the last object in the list
descriptions.remove(descriptions.size()-1);
System.out.println(descriptions.toString());
}
I have five elements in array. I choose element which index is four.
The fifth element is at index 4. if you want to choose the 4th element, it's index will be 3.
Modify your code as following:
int size = descriptions.size();
for(int j = size -1; j>choosenNum; j--)
{
descriptions.remove(j);
}
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<String>();
list.add("a");
list.add("a");
list.add("a");
list.add("a");
list.add("a");
indexToRemove(list, 5);
}
private static void indexToRemove(ArrayList<String> list, int index) {
if (list.size() > index) {
list.remove(index);
System.out.println(index + "th item removed");
} else
System.out.println("Can't remove");
}
You mean a function which will remove the given index element? then try this.
for(int i = descriptions.size()-1; i > indexToDeleteAfter; i--){
descriptions.remove(i);
}
Or, defer to ArrayList:
if(descriptions.size() - 1 > indexToDeleteAfter)
{
descriptions.removeRange(indexToDeleteAfter + 1, descriptions.size() - 1);
}
http://docs.oracle.com/javase/1.4.2/docs/api/java/util/ArrayList.html#removeRange(int,%20int)

deleting an object from an array

I have an array of objects of my custom class and i want to delete a random object(chosen by some criteria). how do i do this and keep the array ordered? naturally, there would be shifting of elements towards the left but i don't quite get the deleting the element part and need help formulating the logic. this is what i am doing but for it doesn't work correctly :(
public static void deleteRecord(Customer[] records, int AccId){
int pos=0; // index
boolean found = false;
for (int i=0; i<count; i++){ // count is the number of elements in the array
if (records[i].get_accountid()==AccId){
found = true;
pos = i;
break;
}
}
if (!found)
System.out.println("The Record doesn't exist");
for (int j=pos+1; j<count; j++) {
records[j-1]= records[j];
}
You can just shift the elements to the left as this will overwrite the item to be deleted.
public void remove(Object[] a, int index) {
for (int i = index + 1; i < a.length && a[i] != null; i++) {
a[i - 1] = a[i];
}
}
Assuming that the first null indicates the end of the elements.
Of course, this is O(n) time and there are data structures like LinkedList that can remove elements in O(1) time.
Unfortunately, you can't just delete an element from an array, not without either leaving empty indices or creating a new array. I would create a new array and use System.arraycopy to simplify copying over your elements. Something like:
Object[] newArr = new Object[arr.length-1];
System.arraycopy(arr,0,newArr,0,index);
System.arraycopy(arr,index+1, newArr, index, newArr.length - index);
return newArr;
Where arr is your original array and index is the random index to remove. Basically, it copies all elements up to the index to remove, and then copies all elements after the index. You can wrap this up in a separate method for simplicity. (Instead of using arraycopy, you could use two for-loops to accomplish the same thing).
I strongly suggest as others have to use a List, which simplifies adding and removing elements.
use List collection e.g:
List<String> list = new ArrayList<String>();
int toDelete = getRandomIndex(lst.size()); //your own implementation
if (toDelete >= 0) {
list.remove(toDelete); // it'll remove and shift elements
}
documentation about List.remove(int):
Removes the element at the specified
position in this list (optional
operation). Shifts any subsequent
elements to the left (subtracts one
from their indices). Returns the
element that was removed from the
list.

Categories

Resources