#Need help working out how to remove a specific type of item from a list/iterator

135 messages · Page 1 of 1 (latest)

lilac canyon
#

I have this class called cargo hold, which can hold containers of 2 types. I need to try and remove containers as the resources they hold are consumed. But at the moment, I can either get everything or nothing to get removed. I am using an iterator to remove elements from the list. Any help?

tulip pollenBOT
#

This post has been reserved for your question.

Hey @lilac canyon! Please use /close or the Close Post button above when you're finished. Please remember to follow the help guidelines. This post will be automatically closed after 300 minutes of inactivity.

TIP: Narrow down your issue to simple and precise questions to maximize the chance that others will reply in here.

lilac canyon
#
    public void consumeResource(ResourceType type, int amount)
            throws InsufficientResourcesException {
        if (type != ResourceType.REPAIR_KIT) {
            throw new IllegalArgumentException();
        }
        int totalResource = getTotalAmountByType(type);
        if (amount > totalResource) {
            throw new InsufficientResourcesException();
        } else {
            Iterator<ResourceContainer> resourceContainers = getResourceByType(type).iterator();
            int consumed = 0;
            int toBeRemoved = 0;
            while (consumed < amount) {
                ResourceContainer resourceContainer = resourceContainers.next();
                consumed += resourceContainer.getAmount();
                toBeRemoved += 1;
            }
            Iterator<ResourceContainer> containers = this.resources.iterator();
            int removed = 0;
            while (removed < toBeRemoved) {
                ResourceContainer resourceContainer = containers.next();
                if (resourceContainer.getType() == ResourceType.REPAIR_KIT) {
                    containers.remove();
                    removed += 1;
                }
            }
        }
    }
#
    public void consumeResource(FuelGrade grade, int amount)
            throws InsufficientResourcesException {
        int totalFuel = getTotalAmountByType(grade);
        if (amount > totalFuel) {
            throw new InsufficientResourcesException();
        } else {
            Iterator<ResourceContainer> fuelContainers = getResourceByType(grade).iterator();
            int consumed = 0;
            int toBeRemoved = 0;
            while (consumed < amount) {
                FuelContainer fuelContainer = (FuelContainer) fuelContainers.next();
                consumed += fuelContainer.getAmount();
                toBeRemoved += 1;
                System.out.println(consumed + " " + toBeRemoved + " " + this.resources);
            }
            Iterator<ResourceContainer> containers = this.resources.iterator();
            int removed = 0;
            while (removed < toBeRemoved) {
                ResourceContainer resourceContainer = containers.next();
                if (resourceContainer.canStore(ResourceType.FUEL)) {
                    FuelContainer fuelContainer = (FuelContainer) resourceContainer;
                    if (fuelContainer.getFuelGrade() == grade) {
                        removed += 1;
                    }
                }
            }
        }
    }
#
    public int getTotalAmountByType(FuelGrade type) {
        int totalFuel = 0;
        Iterator<ResourceContainer> fuelContainers = this.resources.iterator();
        while (fuelContainers.hasNext()) {
            FuelContainer fuelContainer = (FuelContainer) fuelContainers.next();
            if (fuelContainer.getFuelGrade() == type) {
                totalFuel += fuelContainer.getAmount();
            }
        } return totalFuel;
    }
#
    public List<ResourceContainer> getResourceByType(FuelGrade grade) {
        List<ResourceContainer> specifiedFuelGrade = new ArrayList<ResourceContainer>();
        for (int i = 0; i < this.resources.size(); i++) {
            if (this.resources.get(i).canStore(ResourceType.FUEL)) {
                FuelContainer fuelContainer = (FuelContainer) this.resources.get(i);
                if (fuelContainer.getFuelGrade() == grade) {
                    specifiedFuelGrade.add(this.resources.get(i));
                }
            }
        } return (ArrayList) specifiedFuelGrade;
    }
#
public class CargoHold extends Room{

    private int maximumCapacity;
    private List<ResourceContainer> resources;

    public CargoHold(RoomTier tier) {
        super(tier);
        this.maximumCapacity = maximumCapacityFinder(tier);
        this.resources = new ArrayList<ResourceContainer>();
    }
#

all the relevant pieces i think

#

would massively massively appreciate any help

hardy fossil
#

get the iterator and compare the type of each element

#

if item of the type you need to remove - so remove

lilac canyon
#

i thought i was doing it fine

#

but i guess now

#

should it be iterator.remove() to remove it from the original list?

hardy fossil
#

yes

lilac canyon
lilac canyon
hardy fossil
#

what you mean "from original list"?

#

the list, of which was created new list? then no of course

lilac canyon
lilac canyon
hardy fossil
#

iterate the original list

lilac canyon
#

oh yea i did

#

this.resources.iterator

#

sorry ive tried everything i can think of, and am feeling pretty drained

#

i feel like it rly should be working

#

like

#

when i dont have containers.remove() it gives me the initial total resources for the specified typ

#

and when i put containers.remove() the total ends up at 0

#

idk why its like this

#

i can send the whole javafile if thats eaasier?

hardy fossil
#
                if (fuelContainer.getFuelGrade() == grade) {
                    removed += 1;
                }
```you don't remove in here anything
#

you forgot to call iterator.remove()

lilac canyon
#

oh i was testing

#

when i add it back it goes to 0

#

i used to have

#

in the other consume class it has iterator.remove()

hardy fossil
#

post a relevant code that doesn't work

lilac canyon
#

ok 1 se

#
    public void consumeResource(ResourceType type, int amount)
            throws InsufficientResourcesException {
        if (type != ResourceType.REPAIR_KIT) {
            throw new IllegalArgumentException();
        }
        int totalResource = getTotalAmountByType(type);
        if (amount > totalResource) {
            throw new InsufficientResourcesException();
        } else {
            Iterator<ResourceContainer> resourceContainers = getResourceByType(type).iterator();
            int consumed = 0;
            int toBeRemoved = 0;
            while (consumed < amount) {
                ResourceContainer resourceContainer = resourceContainers.next();
                consumed += resourceContainer.getAmount();
                toBeRemoved += 1;
            }
            Iterator<ResourceContainer> containers = this.resources.iterator();
            int removed = 0;
            while (removed < toBeRemoved) {
                ResourceContainer resourceContainer = containers.next();
                if (resourceContainer.getType() == ResourceType.REPAIR_KIT) {
                    containers.remove();
                    removed += 1;
                }
            }
        }
    }
hardy fossil
#

and the problem is that after calling this method, the this.resources list still has same items?

lilac canyon
#

has 0 items

hardy fossil
#

it looks like you select whole list in here java while (consumed < amount) { ResourceContainer resourceContainer = resourceContainers.next(); consumed += resourceContainer.getAmount(); toBeRemoved += 1; }

#

toBeRemoved equals to the size of fuel elements

#

I bet they expect more smart deleting

#

imagine, you have fuel elements in list, that represent amount of fuel in it, like : 1, 2, 3, 10
and they ask you to consume 10 of fuel
you iterate through the list, and since the sum of the elements is < 10 till you count whole of them, you mark whole elements into toBeRemoved

#

even though you need to delete only one last element with value 10

#

and 3 items will be left in list

lilac canyon
#

i think we were told to do like this

hardy fossil
# lilac canyon

is this expected 5 but was 0 about amount of fuel, not about number of elements is the list?

lilac canyon
#

number of elements

#

i think

#

it expects 5 containers

#

but found 0

hardy fossil
#

if that's about container, then, I guess, you need to implement removing as I suggested. But if that's amount of fuel, then just drain containers one by one (and remove if it's empty) till you consume needed amount

lilac canyon
#

i thought that my code was doing that?

#

i guess not

hardy fossil
#

you code doesn't do neither smart deleting (because you delete all the containers in the row), nor "draining" way, because you work with toBeRemoved in the loop where you actually remove elements from original list

lilac canyon
#
    public void consumeResource(ResourceType type, int amount)
            throws InsufficientResourcesException {
        if (type != ResourceType.REPAIR_KIT) {
            throw new IllegalArgumentException();
        }
        int totalResource = getTotalAmountByType(type);
        if (amount > totalResource) {
            throw new InsufficientResourcesException();
        } else {
            ArrayList<ResourceContainer> updatedList = new ArrayList<ResourceContainer>();
            Iterator<ResourceContainer> containers = this.resources.iterator();
            int consumed = 0;
            while (containers.hasNext()) {
                ResourceContainer resourceContainer = containers.next();
                if (consumed < amount) {
                    if (resourceContainer.getType() == ResourceType.REPAIR_KIT) {
                        consumed += resourceContainer.getAmount();
                        containers.remove();
                    }
                }
                updatedList.add(resourceContainer);
            } this.resources = updatedList;
        }
    }
#

@hardy fossil this is now just showing the original values

#

but i feel like this is as u said?

hardy fossil
#
  1. don't do like this:
if (amount > totalResource) {
            throw new InsufficientResourcesException();
        } else {
```If the exception will be thrown, `else` won't be executed anyways. Use it like this: 
```java
if (amount > totalResource) 
            throw new InsufficientResourcesException();

int totalResource = getTotalAmountByType(type);
...
#
  1. in the end you assign o original list the list of removed elements... why?
updatedList.add(resourceContainer);
} this.resources = updatedList;
lilac canyon
#

i thought because i use removed

hardy fossil
#
  1. this: ```java
    while (containers.hasNext()) {
    ResourceContainer resourceContainer = containers.next();
    if (consumed < amount) {
    if (resourceContainer.getType() == ResourceType.REPAIR_KIT) {
    consumed += resourceContainer.getAmount();
    containers.remove();
    }
    }
    updatedList.add(resourceContainer);
    }
lilac canyon
#

it only adds the elements not removed

hardy fossil
#

besides, your code can consume more then needed

#

in here ```
consumed += resourceContainer.getAmount();
containers.remove();

#

imagine you need to remove only 5, but container has 10. But you consume all 10 and remove container

hardy fossil
#

so even though you remove the item from original list

#

it will be in list, because you still add them to temporary list, which will be assigned to original

#

you don't need to use additional list at all

#

you remove using iterator the needed elements

lilac canyon
#
if (consumed < amount) {
                    if (resourceContainer.getType() == ResourceType.REPAIR_KIT) {
                        if ((amount - consumed) < resourceContainer.getAmount()) {
                            int full = resourceContainer.getAmount();
                            resourceContainer.setAmount(full - (amount - consumed));
                            updatedList.add(resourceContainer);
                        }
                        consumed += resourceContainer.getAmount();
                        containers.remove();
                    }
                }
#

to fix 3)

#

also, i think we arent supposed to run the function if error is thrown

#

they want us to end

hardy fossil
#

forget about updatedList

lilac canyon
#

i passed all the error tests

#
    public void consumeResource(ResourceType type, int amount)
            throws InsufficientResourcesException {
        if (type != ResourceType.REPAIR_KIT) {
            throw new IllegalArgumentException();
        }
        int totalResource = getTotalAmountByType(type);
        if (amount > totalResource) {
            throw new InsufficientResourcesException();
        } else {
            Iterator<ResourceContainer> containers = this.resources.iterator();
            int consumed = 0;
            while (containers.hasNext()) {
                ResourceContainer resourceContainer = containers.next();
                if (consumed < amount) {
                    if (resourceContainer.getType() == ResourceType.REPAIR_KIT) {
                        if ((amount - consumed) < resourceContainer.getAmount()) {
                            int full = resourceContainer.getAmount();
                            resourceContainer.setAmount(full - (amount - consumed));
                        }
                        consumed += resourceContainer.getAmount();
                        containers.remove();
                    }
                }
            }
        }
    }
#

ok its testing

#

fingers crossed

#

same thing

#

@hardy fossil

hardy fossil
#

if (consumed < amount) { this condition has to be in while loop

#

if (resourceContainer.getType() == ResourceType.REPAIR_KIT) { why repair_KIT?

#

aren't you supposed to work only with the type that was passed as argument?

#
if ((amount - consumed) < resourceContainer.getAmount()) {
                            int full = resourceContainer.getAmount();
                            resourceContainer.setAmount(full - (amount - consumed));
                        }
                        consumed += resourceContainer.getAmount();
                        containers.remove();
#

you anyways keep to delete container

#

even if it wasn't drained

lilac canyon
#
    public void consumeResource(FuelGrade grade, int amount)
            throws InsufficientResourcesException {
        int totalFuel = getTotalAmountByType(grade);
        if (amount > totalFuel) {
            throw new InsufficientResourcesException();
        } else {
            Iterator<ResourceContainer> containers = this.resources.iterator();
            int consumed = 0;
            while (containers.hasNext()) {
                ArrayList<ResourceContainer> updatedList = new ArrayList<ResourceContainer>();
                ResourceContainer resourceContainer = containers.next();
                if (resourceContainer.getType() != ResourceType.REPAIR_KIT) {
                    FuelContainer fuelContainer = (FuelContainer) resourceContainer;
                    if (fuelContainer.getFuelGrade() == grade) {
                        if ((amount - consumed) < fuelContainer.getAmount()) {
                            int full = fuelContainer.getAmount();
                            fuelContainer.setAmount(full - (amount - consumed));
                            updatedList.add(fuelContainer);
                        }
                        if (consumed < amount) {
                            consumed += fuelContainer.getAmount();
                        } else {
                            updatedList.add(resourceContainer);
                        }
                    } else {
                        updatedList.add(fuelContainer);
                    }
                } else {
                    updatedList.add(resourceContainer);
                } this.resources = updatedList;
            }
        }
    }
#

@hardy fossil

#

it wasnt working using remove

#

so im trying it like this

#

just making a list and not adding any that are removed

#

adding everything else

#

it has worked for 3 tests

#

only 1 test not working now

#

@hazy moat

hazy moat
#

im not sure tbh

#

my first thought is arrays

onyx trout
#

that obviously wont work

#

do you know about list.removeIf()?

lilac canyon
#

list.removeif?

#

no

#

i dont think ive seen that b4

onyx trout
#

removes all elements matching the predicate you give it

#

eg strings.removeIf(str -> str.equals("abc")) removes all elements from strings that equal "abc"

lilac canyon
#

but i need to remove them from the bottom

#

until the amount required is met

onyx trout
#

wait what do you actually want to do

#

how do you want to remove the elements from the list

#

specifically

lilac canyon
#

this is the test thats failing

#
    public void consumeResource(FuelGrade grade, int amount)
            throws InsufficientResourcesException {
        int totalFuel = getTotalAmountByType(grade);
        if (amount > totalFuel) {
            throw new InsufficientResourcesException();
        } else {
            Iterator<ResourceContainer> containers = this.resources.iterator();
            int consumed = 0;
            while (containers.hasNext()) {
                ArrayList<ResourceContainer> updatedList = new ArrayList<ResourceContainer>();
                ResourceContainer resourceContainer = containers.next();
                if (resourceContainer.canStore(ResourceType.FUEL)) {
                    FuelContainer fuelContainer = (FuelContainer) resourceContainer;
                    if (fuelContainer.getFuelGrade() == grade) {
                        if ((amount - consumed) < fuelContainer.getAmount()) {
                            int full = fuelContainer.getAmount();
                            fuelContainer.setAmount(full - (amount - consumed));
                            updatedList.add(fuelContainer);
                        } else if (consumed < amount) {
                            consumed += fuelContainer.getAmount();
                        } else {
                            updatedList.add(resourceContainer);
                        }
                    } else {
                        updatedList.add(fuelContainer);
                    }
                } else {
                    updatedList.add(resourceContainer);
                } this.resources = updatedList;
            }
        }
    }
#

^^^not working

#
    public void consumeResource(ResourceType type, int amount)
            throws InsufficientResourcesException {
        if (type != ResourceType.REPAIR_KIT) {
            throw new IllegalArgumentException();
        }
        int totalResource = getTotalAmountByType(type);
        if (amount > totalResource) {
            throw new InsufficientResourcesException();
        } else {
            Iterator<ResourceContainer> containers = this.resources.iterator();
            int consumed = 0;
            while (containers.hasNext()) {
                ArrayList<ResourceContainer> updatedList = new ArrayList<ResourceContainer>();
                ResourceContainer resourceContainer = containers.next();
                if (resourceContainer.getType() == ResourceType.REPAIR_KIT) {
                    if ((amount - consumed) < resourceContainer.getAmount()) {
                        int full = resourceContainer.getAmount();
                        resourceContainer.setAmount(full - (amount - consumed));
                        updatedList.add(resourceContainer);
                    }
                    if (consumed < amount) {
                        consumed += resourceContainer.getAmount();
                    } else {
                        updatedList.add(resourceContainer);
                    }
                } else {
                    updatedList.add(resourceContainer);
                } this.resources = updatedList;
            }
        }
    }
#

^^^similar function that works, just a different resource type

#

@onyx trout any ideas whats going on?

river estuary
#

First thing I would do is move some of that logic into another method because consumeResource is far too complex to work with.
I'd probably also create a "consume" method in the ResourceContainer class, which accepts an amount to attempt to consume and returns the amount it was able to consume.
You could then simply do consumed += container.consume(amount - consumed) in your loop, which would cut that down quite a bit.

   consumed += resourceContainer.getAmount();```
Maybe I'm mis-reading this, but why are you setting the consumed amount = to the amount remaining in the resource container?
I expect that's producing your strange results.

Also:
```} this.resources = updatedList;```
This statement should not be written on the same line as the closing brace.
lilac canyon
#

@river estuary i literally just fixed it, no clue how

#

but its fixed

#

but ty smsm for the help