Reputation: 29
I am trying to build a model in Netlogo in which I have two lists of lists which I call offerlist and bidlist, the two list are structured as follows:
let offerlist [[offer_1 price_1 id_of_agent] [offer_2 price_2 id_of agent]...]
let bidlist [[bid_1 price_1 id_of_agent] [bid_2 price_2 id_of agent]...]
Basically every inner list contains the offer or bid of a certain agent, the price and the id of the agent submitting a certain offer/bid
I am trying to iterate over the two lists to simulate a market place, which means that I compare the prices of a certain offer and of a certain bid and if the conditions are met I would like to make a transaction happen reducing the offer in the offerlist and the bid in the bidlist. To be more specific I tried to do it like this:
to-report replace-subitem [index1 index2 lists value]
let old-sublist item index1 lists
report replace-item index1 lists (replace-item index2 old-sublist value)
end
foreach offerlist[[x]->
foreach bidlist[[y]->
if item 1 x < item 1 y[
set bidlist replace-subitem (position y bidlist) 0 bidlist 0
set offerlist replace-subitem (position x offerlist) 0 offerlist 0
]
]
]
The replace-subitem reporter works when it comes to change items of inner lists of a list of lists and I found it on Stack Overflow. Unfortunately using this I get an error since instead of the index of the items of the list I get a TRUE/FALSE probably because it is not possible or not functional to change items of the lists while I iterate through them. Is there a way to iterate through the lists while modifying the elements if certain conditions are met? If so which is the best way to do it?
Upvotes: 0
Views: 457
Reputation: 10291
Thanks for the comment- One way to do this would be to use foreach
with indices rather than with the list items directly, so you can use the index from one list to refer to another. With this setup:
globals [ offerlist bidlist ]
to setup
ca
set offerlist [ [ 25 15 1 ] [ 75 25 2 ] [ 23 35 3 ] ]
set bidlist [ [ 15 20 1 ] [ 90 30 2 ] [ 20 40 3 ] ]
reset-ticks
end
Then (assuming the lists are always the same length) you can use the length of whichever list to build indices and iterate over every one. More detail in comments:
to update-lists
foreach range ( length offerlist ) [
ind ->
; Get the first items from each current sublist
let offer-item item ind offerlist
let bid-item item ind bidlist
; If the offer is greater than the bid, get the
; difference between those values
if first offer-item > first bid-item [
let dif first offer-item - first bid-item
; Update the offer item with the difference value
set offer-item replace-item 0 offer-item dif
; Update the bid-item with 0
set bid-item replace-item 0 bid-item 0
; Go back to the index value to update both the
; offerlist and the bidlist
set offerlist replace-item ind offerlist offer-item
set bidlist replace-item ind bidlist bid-item
]
]
print offerlist
print bidlist
end
Which takes you from the input lists that look like:
[[25 15 1] [75 25 2] [23 35 3]]
[[15 20 1] [90 30 2] [20 40 3]]
to the output of:
[[10 15 1] [75 25 2] [3 35 3]]
[[0 20 1] [90 30 2] [0 40 3]]
If you'd prefer a map
version, I think you have to do it in two steps:
to update-lists-map
; Make a temporary offerlist by mapping over
; the current offerlist and bidlist, and replacing
; the first item as appropriate
let newoffers ( map [
[ o_ b_ ] ->
ifelse-value ( first o_ > first b_)
[ replace-item 0 o_ ( first o_ - first b_ )]
[ o_ ]
] offerlist bidlist )
; Make a temporary bidlist by mapping over
; the current offerlist and bidlist, and zeroing
; the first item as appropriate
let newbids ( map [
[ o_ b_ ] ->
ifelse-value ( first o_ > first b_)
[ replace-item 0 b_ 0 ]
[ b_ ]
] offerlist bidlist )
; overwrite the original offer and bid lists
set offerlist newoffers
set bidlist newbids
print offerlist
print bidlist
end
Upvotes: 2