How to get rid of adjacent String inside arraylist? - java

what command of arraylist should I use in order to get rid of adjacent Strings. Suppose I have an arraylist of allOrders<String>:
Crushed Turtle
10 Coins Off
10 Coins Off
Mushroom Veal
In the example above I should not get 2 adjacent lines of the same thing. What method of arraylist should I use?
Note: only adjacent should be removed/replaced. The following is legit:
Firey Flower Pasta
Crushed Turtle
Firey Flower Pasta
Crushed Turtle

You can get an Iterator from your List, iterate over the entire list and keep track of the latest value. If the current value is equal to the latest, you delete it.
Something like this:
Iterator<String> iterator = allOrders.iterator();
String latest = "";
while (iterator.hasNext()) {
String current = iterator.next();
if (current.equals(latest)) {
iterator.remove();
}
latest = current;
}

There is no built-in method for doing what you want, but you could create a stripped copy (stripped) of your list like this:
List<String> stripped = new ArrayList<String>();
String latestOrder = null;
for (String order : allOrders) {
if (!order.equals(latestOrder)) {
stripped.add(order);
}
latestOrder = order;
}

Write your own loop which will iterate over pair of elements and if they are equal remove one of them (you can use remove(index) from List).
for (int i=list.size()-1; i>0; i--){
if (list.get(i-1).equals(list.get(i))){
list.remove(i);
}
}
I prefer to iterate from end to start to avoid problems with elements shifting.
DEMO:
List<String> list = new ArrayList<>();
list.add("Crushed Turtle");
list.add("10 Coins Off");
list.add("10 Coins Off");
list.add("10 Coins Off");
list.add("Mushroom Veal");
for (int i = list.size() - 1; i > 0; i--) {
if (list.get(i - 1).equals(list.get(i))) {
list.remove(i);
}
}
System.out.println(list);
Output: [Crushed Turtle, 10 Coins Off, Mushroom Veal]

This works. You iterate over the List and compare consecutive elements if two equals you remove one of them.
ArrayList<String> l = new ArrayList<String>();
l.add("a");
l.add("b");
l.add("b");
l.add("b");
l.add("b");
l.add("d");
System.out.println(l);
for(int i = 0; i < l.size() - 1; i++){
if(l.get(i).equals(l.get(i+1))){
l.remove(i+1);
i--;
}
}
System.out.println(l);

Related

Java - Map<String, List<Object>> iterate through list and skip first N entries

I'm pretty new to Java so please be lenient. I have a map, Map<K,V>. I need to iterate through the values, skip the first N indices and add what remains to another list for processing.
For example
Key: foo
Value: [id=001, name=Fred, job=Mailman, age=51],
[id=002, name=Johan, job=Musician, age=335],
[id=003, name=Alice, job=Finance, age=49],
[id=004, name=Marcus, job=Developer, age=41]
I'm sorting by age in descending order and I need to skip over the first N list entries.
The code below is where I'm currently at. Any help is appreciated. Thank you.
List<Object> finalList = new ArrayList<Object>();
List<Object> sortedList = new ArrayList<Object>();
Map<String, List<Object> map = getMapFn();
for(List<Object> anotherList : map.values()) {
Collections.reverse(anotherList);
sortedList = anotherList;
for(Object o : sortedList) {
int skipN = N;
for(int i = 0; i < sortedList.size(); i++) {
if(i < skipN) {
continue;
}
}
finalList.add(o);
}
}
Final Goal:
If N=2,
finalList = [id=003, name=Alice, job=Finance, age=49],
[id=004, name=Marcus, job=Developer, age=41]
in your code,item in sortedList will always add to finalList
int skipN = N;
int index = 0;
for(Object o : sortedList) {
if(index<skipN){
index++;
contine;
}
index++;
finalList.add(o);
}
or use jdk1.8 stream
sortedList.stream().skip(skipN).collect(Collectors.toList())
You don't need the inner loop at all.
int skipN = N;
for(Object o : sortedList) {
if (skipN-- > 0) {
continue;
}
finalList.add(o);
}
Your 2nd and 3rd for loop will perform the same task. I think you do not want this.
So, remove 2nd loop. 3rd loop will be:
get the Nth item from your sortedList using sortedList.get(i)
And, add it into your finalList
for(int i = 0; i < sortedList.size(); i++) {
if(i < skipN) {
continue;
}
finalList.add(sortedList.get(i));
}
Use a sublist of the items to remove and delete all items from it:
for (List<Object> list : map.values()) {
Collections.reverse(list);
list.subList(0, Math.min(list.size(), N)).clear();
}
This creates a sublist that contains the first N items (or the whole list if there are less than N items), then deletes all the items in the sublist via .clear().
Modifications to sublists are reflected in the original list, so the deletions are reflected in the original list.
For interest sake, here's a one-line version:
map.values().stream()
.peek(Collections::reverse)
.map(list -> list.subList(0, Math.min(list.size(), N))
.forEach(List::clear);
but it doesn't look as clear as the multi-line version above.

Split an Arraylist into multiple variable length Arraylists

I have two ArrayLists. The first list contains some x number of elements these elements are again ArrayLists. The second list contains only integer values.
Second list size is always less than first list size Example of first list is: [[TC1,TC1_1],[,TC1_2],[TC2,TC2_1],[TC3,TC3_1][,TC3_2],[TC4,TC4_1][,TC4_2][,TC4_3],[TC5,TC5_1],[TC6,TC6_1]]
Example of second list is [0,2,3,5,8,9].This second Araylist elements points to 1st arraylist where the 1st element of individual ArrayList elements of first arraylist is not empty
Now the requirement is 1st list should be split into 6 lists where 6 is 2nd list size. Output should be as below.
Of the 6 new lists 1st list would contain elements of main list from 0th to 1st index. The 2nd list would contain elements of main list from 3rd index. The 3rd list would contain elements of main list from 4th to 5th index and so on..finally output will be as below
`[[[TC1,TC1_1],[,TC1_2]]
[[TC2,TC2_1]]
[[TC3,TC3_1][,TC3_2]]
[[TC4,TC4_1][,TC4_2][,TC4_3]]
[[TC5,TC5_1]]
[[TC6,TC6_1]]]
private ArrayList getTCsIncludingSubTcs(ArrayList TCIndexes,ArrayList alTCs) {
//List tempSubList=new ArrayList();
ArrayList finalTCS=new ArrayList();
for(int j=0;j<TCIndexes.size();j++){
int TCIndex=(int)TCIndexes.get(j);
if(j==0 && TCIndexes.size()==1){
//List tempSubList=new ArrayList(alTCs.subList(TCIndex,(int)alTCs.size()));
List tempSubList=getSubArrayList(TCIndex,(int)alTCs.size(),alTCs);
finalTCS.add(tempSubList);
break;
}
int nextTCIndex=j+1;
System.out.println(nextTCIndex);
if(j==TCIndexes.size()-1){
List tempSubList=getSubArrayList(TCIndex,(int)alTCs.size(),alTCs);
finalTCS.add(tempSubList);
break;
}
List tempSubList=getSubArrayList(TCIndex,(int)alTCs.size(),alTCs);
finalTCS.add(tempSubList);
System.out.println("finalTCS :"+finalTCS);
}
System.out.println("fc size"+finalTCS.size());
return finalTCS;
}
Try this code.
public class Test {
private List<List<String>> getTcsIncludingSubTcs(ArrayList<Integer> tcIndexes,ArrayList<String> alTcs) {
List<List<String>> finalTcs=new ArrayList<>();
List<String> temp = new ArrayList<>();
int size = tcIndexes.size();
int i= alTcs.size();
int k = 0;
for(int j=0; j<alTcs.size(); j++){
if(( j != 0 && j % size == 0 && i >= size))
{
temp = new ArrayList<>();
k++;
}
i--;
temp.add(alTcs.get(j));
if(finalTcs.contains(temp))
finalTcs.remove(k);
finalTcs.add(k, temp);
}
return finalTcs;
}
public static void main (String arg[])
{
ArrayList<String> data1 = new ArrayList<>();
data1.add("TC1");
data1.add("TC2");
data1.add("TC3");
data1.add("TC4");
data1.add("TC5");
data1.add("TC6");
data1.add("TC7");
data1.add("TC8");
data1.add("TC9");
data1.add("TC10");
ArrayList<Integer> data2 = new ArrayList<>();
data2.add(0);
data2.add(3);
data2.add(6);
Test t = new Test();
List<List<String>> list = t.getTcsIncludingSubTcs(data2, data1);
for(List<String> l : list)
System.out.println(l);
}
}
Output:
[TC1, TC2, TC3]
[TC4, TC5, TC6]
[TC7, TC8, TC9, TC10]
One more solution is ,
we have source list and start index list.Using these two lists generate end index list.Now use start index list and end index list to generate the required final output

Arraylist remove

Need to do a method which takes ArrayList<ArrayList<<Integer>> and an Integer which then returns an ArrayList<ArrayList<<Integer>> from the orginal ArrayList<ArrayList<<Integer>> which do not contain the Integer argument e.g
ArrayList<ArrayList<<Integer>>
[[1,2,3],[7,5],[4,4,2],[8,12,3]] and Integer 2 should return
[[7,5],[8,12,3]]. arraylist of arraylist integers.
not entirely sure how to access the inner loop
You can use contains() rather than worrying about writing an inner loop yourself.
Also, removing elements from lists while iterating is tricky. So, since you are not modifying the list and seem to be expected to return one, then just make a new list and add rather than remove.
public static ArrayList<ArrayList<Integer>> removeTheNumber(ArrayList<ArrayList<Integer>> n , Integer p){
ArrayList<ArrayList<Integer>> a = new ArrayList<>();
for(int i=0; i < n.size(); i++){
ArrayList<Integer> innerList = n.get(i);
if (!innerList.contains(p)) a.add(innerList);
}
return a;
}
You can use .contains of the inner lists to check as Integer class supports this. Below is a function and its test.
public ArrayList<ArrayList<Integer>> removeTheNumber(ArrayList<ArrayList<Integer>> lists, Integer n) {
ArrayList<ArrayList<Integer>> result = new ArrayList<>();
for (ArrayList<Integer> list: lists ) {
if (!list.contains(n))
result.add(list);
}
return result;
}
#Test
public void testRemoveNumber() {
ArrayList<ArrayList<Integer>> lists = new ArrayList<>();
lists.add(Lists.newArrayList(2,7,8));
lists.add(Lists.newArrayList(6,7,9));
lists.add(Lists.newArrayList(3,2,6));
ArrayList<ArrayList<Integer>> result = removeTheNumber(lists, 2);
Assert.assertArrayEquals(lists.get(1).toArray(new Integer[]{}), result.get(0).toArray(new Integer[]{}));
result = removeTheNumber(lists, 7);
Assert.assertArrayEquals(lists.get(2).toArray(new Integer[]{}), result.get(0).toArray(new Integer[]{}));
result = removeTheNumber(lists, 6);
Assert.assertArrayEquals(lists.get(0).toArray(new Integer[]{}), result.get(0).toArray(new Integer[]{}));
}
If you want to use two loops you can write it like this (where array is your input array, and toSearch is your integer):
ArrayList<ArrayList<Integer>> arrayToReturn = new ArrayList<>();
for(ArrayList<Integer> listInner : array){
boolean found = false;
for(Integer elem : listInner) {
if (elem == toSearch)
found=true;
}
if(found!=true)
arrayToReturn.add(listInner);
}
arrayToReturn.stream().forEach(System.out::println);
Of course i reccomend to use java 8, and then you can simply write it like this:
arrayToReturn = array.stream().filter(elem ->
!elem.contains(toSearch)).collect(
Collectors.toCollection(ArrayList<ArrayList<Integer>>::new));
arrayToReturn.stream().forEach(System.out::println);
Let's pretend you have
ArrayList<ArrayList<Integer>> myArrayList = [[1,2,3],[7,5],[4,4,2],[8,12,3]];
for (int i = 0; i < myArrayList.length; i++) {
//...
}
Your variable i is iterating through the initial ArrayList, which contains another ArrayList. So, myArrayList[i] will yield another ArrayList, which also has a length.
Building on this we have:
for (int i = 0; i < myArrayList.length; i++) {
ArrayList<Integer> inner = myArrayList.get(i);
for (int j = 0; j < inner.length; j++) {
//now we may check for the existence of our integer
}
}

Better way to loop through the List<String> and remove items

I have a List and I'm looping through it removing items in the List if there is a match.
I'm using i = -1 if the item in the List is removed. But it loops through from the beginning again. Is there a better way to do this?
private List<String> populateList(List<String> listVar) {
List<String> list = new ArrayList<String>();
list.add("2015-01-13 09:30:00");
list.add("2015-01-13 06:22:12");
list.add("2015-01-12 05:45:10");
list.add("2015-01-12 01:52:40");
list.add("2015-01-12 02:23:45");
return list;
}
private void removeItems() {
List<String> list = new ArrayList<String>();
list = populateList(list);
System.out.println("List before modification : "+list);
for (int i = 0; i < list.size(); i++) {
String dateNoTime = list.get(i).split(" ")[0];
System.out.println(" Going over : "+list.get(i));
if(!dateNoTime.equalsIgnoreCase("2015-01-13")) {
System.out.println(" Removing : "+list.get(i));
list.remove(i);
i = -1; //This is making the loop start from scratch. Is there a better way?
}
}
System.out.println("List after modification: "+list+"\n\n");
}
Java's List<T> provides a better way of removing items from it by using ListIterator<T>:
ListIterator<String> iter = list.listIterator();
while (iter.hasNext()) {
String s = iter.next();
String dateNoTime = s.split(" ")[0];
if(!dateNoTime.equalsIgnoreCase("2015-01-13")) {
iter.remove();
}
}
With Java-8, you can simplify the entire thing to:
List<String> filtered = list.stream().filter(item -> item.split(" ")[0]
.equalsIgnoreCase("2015-01-13"))
.collect(Collectors.toList());
I think this is the shortest way to remove items from the list by checking them one-by-one. (I mean 'shortest' in terms of code size, not complexity-wise).
When you're using an index to iterate through a list, and you're removing items from the list, you need to be careful about how you handle the index. (Doing the remove through the iterator as in #dasblinkenlight's answer is better in this case, but there are other similar situations where it's not possible.)
Suppose you just deleted the line that resets i:
for (int i = 0; i < list.size(); i++) {
String dateNoTime = list.get(i).split(" ")[0];
System.out.println(" Going over : "+list.get(i));
if(!dateNoTime.equalsIgnoreCase("2015-01-13")) {
System.out.println(" Removing : "+list.get(i));
list.remove(i);
//i = -1; //This is making the loop start from scratch. Is there a better way?
}
}
Now, when i==2, you decide you need to remove the element. When you do so, the item that was element 3 then becomes element 2, and the element that was element 4 then becomes element 3, and so on.
But then you go back up to the top and increment i. It is now 3. The result is that the element that was element 3, but is now element 2, is never examined at all. It gets skipped.
There are a couple ways to deal with this.
One is to make sure i doesn't get incremented. I've seen good programmers do things like this:
for (int i = 0; i < list.size(); i++) {
String dateNoTime = list.get(i).split(" ")[0];
System.out.println(" Going over : "+list.get(i));
if(!dateNoTime.equalsIgnoreCase("2015-01-13")) {
System.out.println(" Removing : "+list.get(i));
list.remove(i);
i--; // Move "i" backwards so that no elements are skipped
}
}
Personally, I dislike modifying an index inside a for loop like this, so I'd be happier with
int i = 0;
while (i < list.size()) {
String dateNoTime = list.get(i).split(" ")[0];
System.out.println(" Going over : "+list.get(i));
if(!dateNoTime.equalsIgnoreCase("2015-01-13")) {
System.out.println(" Removing : "+list.get(i));
list.remove(i);
} else {
i++;
}
}
[Note that in both cases, it's important to use list.size() in the termination condition, and not save the original value in a variable. The list size will change, and you want to use the new size when checking for termination.]
Another solution that may be appropriate in some cases is to go backward through the list:
for (int i = list.size() - 1; i >= 0; i--)
String dateNoTime = list.get(i).split(" ")[0];
System.out.println(" Going over : "+list.get(i));
if(!dateNoTime.equalsIgnoreCase("2015-01-13")) {
System.out.println(" Removing : "+list.get(i));
list.remove(i);
}
}
which doesn't have the problem when elements are shifted.
You can use Iterator interface which has remove method.
Iterator<String> iterator = list.iterator();
while (iterator.hasNext())
{
String next = iterator.next();
String dateNoTime = next.split(" ")[0];
if(!dateNoTime.equalsIgnoreCase("2015-01-13")) {
System.out.println(" Removing : "+next);
iterator.remove();
}
}
Use Iterators.
Javadoc for Iterator says the following
Iterators allow the caller to remove elements from the underlying collection during the iteration with well-defined semantics.
Or you can use guava API to achieve it.
FluentIterable
.from(list)
.transform(new Function<String, String>(){
#Override
public void apply(String input){
return input.split(" ")[0];
}
}).filter(new Predicate<String>(){
#Override
public boolean apply(String input){
return input.equalsIgnoreCase("2015-01-13");
}
}).toList();

What process can be used to compare elements from two separate lists?

I need to first access and then compare elements from two separate lists and based on whichever element has the smaller value, remove the lesser element and assign it a position within a third list. How do I accomplish this?
I believe you can just add the elements of both the list in a new list of one of the list and then sort it in ascending order e.g. below(pseudo code):
List<Integer> list1 = Arrays.asList(2,4,5);
List<Integer> list2 = Arrays.asList(2,6,8,9,12,56);
List<Integer> mergedList = new ArrayList<Integer>();
mergedList.addAll(list1);
mergedList.addAll(list2);
Collections.sort(mergedList);
Now mergedList should have sorted elements.
Just for your learning, find a sample manual merge program below:
List<Integer> list1 = Arrays.asList(2,4,5);
List<Integer> list2 = Arrays.asList(2,6,8,9,12,56);
List<Integer> mergedList1 = new ArrayList<Integer>();
mergedList1.add(list1.get(0));
for(int indx = 1; indx< list1.size(); indx++){
int valueToMerge = list1.get(indx);
boolean merged = false;
for(int indx1 = 0; indx1< mergedList1.size(); indx1++){
if(mergedList1.get(indx1) > valueToMerge){
//add the value in middle
mergedList1.add(indx1, valueToMerge);
merged = true;
break;
}
}
if(!merged){
//add the value in the end
mergedList1.add(valueToMerge);
}
}
for(int valueToMerge: list2){
boolean merged = false;
for(int indx1 = 0; indx1< mergedList1.size(); indx1++){
if(mergedList1.get(indx1) > valueToMerge){
//add the value in middle
mergedList1.add(indx1, valueToMerge);
merged = true;
break;
}
}
if(!merged){
//add the value in the end
mergedList1.add(valueToMerge);
}
}

Categories

Resources