NETLOGO:遍历两个列表列表并动态更改项目

时间:2018-07-08 10:12:56

标签: netlogo nested-lists

我正在尝试在Netlogo中构建模型,其中有两个列表列表,分别称为要约列表和出价列表,这两个列表的结构如下:

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]...]

基本上每个内部列表都包含特定代理商的要约或出价,提交特定出价/要约的代理商的价格和ID

我试图遍历两个列表以模拟一个市场,这意味着我将比较某个报价和某个出价的价格,如果条件满足,我希望进行交易以减少要约列表中的要约和出价列表中的要约。 更具体地说,我尝试这样做:

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
]
]
]

replace-subitem报告程序在更改列表列表的内部列表的项目时起作用,我在Stack Overflow上找到了它。 不幸的是,使用此方法会出现错误,因为我得到的是TRUE / FALSE而不是列表项的索引,这可能是因为在遍历列表项时无法或无法更改列表项。 如果满足某些条件,是否可以在修改元素的同时迭代列表?如果是这样,那是最好的方法?

1 个答案:

答案 0 :(得分:2)

感谢注释-一种实现方法是将foreach与索引一起使用,而不是直接与列表项一起使用,因此您可以使用一个列表中的索引来引用另一个。使用此设置:

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

然后(假设列表的长度始终相同),您可以使用任一列表的长度来构建索引并遍历每个索引。在评论中有更多详细信息:

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

其中哪个将带您进入如下输入列表:

[[25 15 1] [75 25 2] [23 35 3]]
[[15 20 1] [90 30 2] [20 40 3]]

输出到:

[[10 15 1] [75 25 2] [3 35 3]]
[[0 20 1] [90 30 2] [0 40 3]]

如果您希望使用map版本,我认为,您必须分两个步骤进行操作:

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