The idiomatic way to do this in other languages without iterator semantics is to iterate through the list backwards.
For example:
public static List<Object> removeAll(List<Object> target, Object toRemove) {
for(Integer i = target.size() - 1; i >= 0; i--) {
if(target[i].equals(toRemove)) {
target.remove(i);
}
}
return target;
}
Answer from Alex Tennant on Stack ExchangeThe idiomatic way to do this in other languages without iterator semantics is to iterate through the list backwards.
For example:
public static List<Object> removeAll(List<Object> target, Object toRemove) {
for(Integer i = target.size() - 1; i >= 0; i--) {
if(target[i].equals(toRemove)) {
target.remove(i);
}
}
return target;
}
I don't know if it's a best practice, but one way to reverse your approach and make a second list of the items you want to keep, then once you're done iterating, reassign that to your primary list.
So, using your code, it would be:
List<Integer> list = new ArrayList<Integer>();
list.add(1);
list.add(2);
list.add(3);
List<Integer> listToKeep = new ArrayList<Integer>();
for (Integer num : list) {
if (num != 1){
listToKeep.add(num);
}
}
list = listToKeep;
System.out.println(list);
Does anyone have a code example of how to iterate through a list and remove any list items that match the items in another list? So, say I have a list of CDs and a list of LPs, I want to look through the list of CDs and remove any that are for the same artist and album as an item in the list of LPs. I'm thinking I'm probably going to need a map but I've never written a map before and can't seem to find any examples of them that remove things.
UPDATE: Thanks for all the input guys. I'm totally going to save this thread and use all this stuff in the future. As for the current scenario. I found a different solution. I was attempting to avoid an error message but the client actually wants to see the error message SO totally different scenario :)
I'd convert your list to sets, and use set.contains, and set.removeAll. Check out the set docs.
https://www.salesforce.com/us/developer/docs/apexcode/Content/apex_methods_system_set.htm#apex_System_Set_methods
I'd do it like this (provided I am understanding your question). it could be a set of anything, I'm just using Ids since I don't know what your data type is. You could the convert the set back into a list if you need. Or you can use the suggestion below of iterating the list, recording the index position (which might be a pain/inefficient to get since lists don't have a contains method, so you'd need to iterate and search the list for every element).
//set created from your first list, Im calling it listA (provided your list is a list of ids)
set<id> firstSet = new set<id>(listA);
//set created from your second list, which I'm calling listB (provided your list is a list of ids)
set<id> secondSet = new set<id>(listB);
//temp variable to hold the things to delete
list<id> thingsToRemove = new list<id>();
//iterate the first set
for(id thisId : firstSet)
{
//see if this thing is in the second set
if(secondSet.contains(thisId))
{
//if so, then add it to our list of things to remove
thingsToRemove.add(thisId);
}
}
//remove the things from the set
firstSet.removeAll(thingsToRemove);
Edit: Just realized that if you are actually storing albums as sObjects and can retrieve with SOQL, none of this is necessary. It would be one line:
List<Album> filteredCDs = [ Select Id, Name... etc from Album Where Id in : CDs and Id Not in : LPs ];
Given that, I bet all my assumptions were wrong, eh? Perhaps I should have asked more questions, but hey, nothing like writing a novel about code... while at work... supposedly working on work related code...
The problem with lists is you can only remove items by passing an index. Once it's removed, the indeces are reset, so it's pretty much impossible to iterate through a list and remove items while you're in the same loop.
Here's how I'd do it without maps (and by making big assumptions about your existing code):
private List<Album> filterCDs(List<Album> CDs, List<Album> LPs) {
List<Album> filteredCDs = new List<Album>();
for ( Album CD: CDs) {
for ( Album LP : LPs ) {
if ( LP.ArtistName != CD.ArtistName && LP.AlbumName != CD.AlbumName )
filteredCDs .add(CD);
}
}
return filteredCDs;
}
So this doesn't actually remove anything, it just only returns the cds that don't appear in the LP list. If your lists are large, this is crazy inefficient though, with the number of comparisons being CDs.size() * LPs.size().
Maps are not as scary as they seem, and are extremely useful! They're basically the same as a list/array, but can use an index other than an integer. What's cool about maps is you can build one with SOQL, and it gives you a kind of list where each index is the ID of the record.
Here's how I'd do it with a map (assuming albums are an sObject and not just a Class):
private List<Album> filterCDs(List<Album> CDs, List<Album> LPs) {
Map<Id, Album> LPMap = new Map<Id, Album>([ Select Id from Album where Id in : LPs ]);
/*
^ returns a kind of list where the indexes are the Ids of each record, like:
LPMap = {
'albumid0' = Album{
Id = 'albumid0'
},
'alumbid1' = Album{
Id = 'albumid1'
},...
}
*/
List<Album> filteredCDs = new List<Album>();
for ( Album CD: CDs) { // iterate through CDs
if ( !LPMap.containsKey(CD.Id) ) // if the LP map does *not* contain this CD id
filteredCDs.add(CD); // add it to the new list
}
return filteredCDs;
}
Calling LPMap.containsKey(some_album_id) is better than iterating through the entire list and physically checking if an album with the same title/artist is present. It's similar to checking whether or not LPMap.get(some_album_id) == null. And now the number of comparisons is just the size of the CDs list.
Definitely find more info about maps and how to build them manually with .put(key, value). Removing is just .remove(key).
Anyway, hope that makes some amount of sense... I'd have to know more about how you're already organizing things to know whether or not everything I've just typed is utterly useless or not!
salesforce - delete multiple objects which are inside array in Apex - Stack Overflow
salesforce - Iterating Through A List And Removing Duplicate Items in apex - Stack Overflow
collections - Remove all duplicate and the original elements from a list - Stack Overflow
salesforce - How to remove a class instance from a List of class - Stack Overflow
Videos
As long as you don't use the shorthand iteration technique for(Object a : Objects) and use a traditional for loop, it works fine (you must traverse the list in reverse order as the example shows)
Try this:
for (Integer i = (companyinfos.size()-1) ; i>= 0 ; i--){
String s = companyInfos[i];
if(s.contains('a')){
companyinfos.remove(i);
}
}
Salesforce prohitbits (or at least used to do that earlier) removing items from list while traversing it.
So, the solution would be to create another list, store all desired elements in there. For e.g.
List<CompanyInfo> companyinfos=new List<companyinfos>();
List<CompanyInfo> finalList=new List<companyinfos>();
companyinfos.add(***);
....
integer index=0;
For(CompanyInfo info: companyinfos)
{
if(info.item!=****)
{
finalList.add(info);
}
}
companyinfos = finalList;
