簡體   English   中英

如何解析 Netlogo 中的字符串?

[英]How can I parse a string in Netlogo?

語境

對於我的 model,我想要一個輸入,用戶可以在其中輸入一系列值。

例如

在此處輸入圖像描述

我想從上面顯示的輸入中得到一個包含五個數字的列表,例如[0.5 0.2 0 0.2 0.5] ,因此我可以使用他們輸入的數字進行一些計算。

問題

不幸的是,如果我將類型設置為字符串,那么像上面這樣設置輸入會吐出"0.5 0.2 0 0.2 0.5" 如果我將類型設置為數字,它將只允許輸入一個數字。

那么,如何以空格為基礎(即“”)解析字符串? 我也對替代品持開放態度,盡管我更願意將其保留在 Netlogo 中(例如,不讀取值的文本文件)以使其更容易更改,因為我懷疑它會被很多人玩弄。

我試過的

我曾嘗試使用read-from-string ,但它也不喜歡像上面那樣輸入一系列數字。 我還嘗試使用字符串擴展名( https://github.com/NetLogo/String-Extension )中的explode function ,但我的 Netlogo 版本(6.2.0)不喜歡來自該擴展名的 ZDB974238714CAtADE634 的 ZDB974238714CAtADE634請允許我使用它。

我對 NetLogo 很陌生,如果我的問題很愚蠢或者我沒有說清楚,很抱歉!

您可以結合positionsubstringread-from-stringfput

這是工作流程:

  1. 創建一個循環,只要字符串包含多個數字(= 只要它包含至少一個空格,使用position " " string檢查);
  2. 提取從第一個字符到排除的第一個空格的 substring (使用substring完成);
  3. 將 substring 作為數值讀取(使用read-from-string )並將其添加到list-of-numbers (使用fput );
  4. 刪除字符串中的第一個數字(使用position " " stringrepeatbut-first )並再次開始循環;
  5. 當循環條件評估為FALSE時,這意味着字符串中只剩下一個數字。 將最后一個數字(即整個剩余的字符串)添加到循環外的list-of-numbers ,這一切都完成了。

下面的過程是一個報告過程,它執行這個工作流並報告從字符串中讀取的值列表(它只需要界面中的user-string輸入框):

to-report convert-user-string [str]
  let temp-string user-string
  let list-of-numbers (list)
  
  while [position " " temp-string != FALSE] [
   let next-number-as-string  (substring temp-string 0 position " " temp-string)
   set list-of-numbers lput (read-from-string next-number-as-string) (list-of-numbers)
   
   repeat (position " " temp-string + 1) [
     set temp-string (but-first temp-string)
   ]
  ]
  
  set list-of-numbers lput (read-from-string temp-string) (list-of-numbers)
  
  report list-of-numbers
end

例如:

observer> set user-string "0.5 0.2 0 0.2 0.5"
observer> show user-string
observer: "0.5 0.2 0 0.2 0.5"
observer> show convert-user-string user-string
observer: [0.5 0.2 0 0.2 0.5]


我上面發布的過程是我制作的初始代碼的精簡版,我將在下面留下大量評論:

globals [
  list-of-numbers   ; The list where values from the input string will be stored.
  
  temp-string       ; A temporary variable being the alter-ego of 'user-list'. This is needed because
                    ; the 'trim-string-to-next-nonspace' procedure won't let me change the value of
                    ; 'user-string' directly (I am not sure why, anyone please feel free to say if I'm
                    ; missing something here) but also because you might want to keep the value of the
                    ; user input intact - hence we use this 'temp-string' to trim the string without worries.
]


to convert-user-string [str]
; As long as there are at least two numbers in the string (identified by the presence of at least one
; space), the while loop extracts the first number with 'substring' and then assigns it as a numeric
; value to 'list-of-numbers' by using 'read-from-string' and 'lput'. At that point, it trims the
; string up to the next non-space character.
; When there is only one number left in the string (identified by the absence of spaces in the string),
; the 'more-than-one-number-in-string? temp-string'condition evaluates as 'FALSE' and the while loop
; stops. At that point, the last line of code adds what is left of the string (i.e. the last number)
; to the 'list-of-numbers' list.
  
  set list-of-numbers (list)   ; Initiating this variable as a list in order to be able to use 'lput'.
  
  set temp-string user-string
  
  while [more-than-one-number-in-string? temp-string] [
   let next-number-as-string  (substring temp-string 0 position-of-next-space temp-string)
   set list-of-numbers lput (read-from-string next-number-as-string) (list-of-numbers)
   
   trim-string-to-next-nonspace temp-string
  ]
  
  set list-of-numbers lput (read-from-string temp-string) (list-of-numbers)
end


to-report more-than-one-number-in-string? [str]
; This reporter is needed as a condition for the while loop in 'convert-user-string'. The reason is that
; the 'position' command (used by the 'position-of-next-space' procedure) reports either a number (i.e.
; the position of the character in the given string) or 'FALSE' (in case the item is not present in the
; string). Therefore, this procedure is needed in order to get either TRUE or FALSE to be used in the
; while condition.
  
  ifelse (position-of-next-space str = FALSE)
   [report FALSE]
   [report TRUE]
end


to-report position-of-next-space [str]
; Simply reporting the position of the next space in the string. Note that positions (indexes) in NetLogo
; are numbered starting from 0.
  
  report position " " str
end


to trim-string-to-next-nonspace [str]
; By using 'but-first' repeatedly, this procedure gets rid of the first number (which has already been stored
; in 'list-of-numbers' by the 'convert-user-string' procedure) and the following space in the string.
; Note that the '+ 1' bit is needed because the count of positions in NetLogo starts from 0 for the first item.

  let x temp-string
  
  repeat (position-of-next-space temp-string + 1) [
   set x (but-first x) 
  ]
  
  set temp-string x
end

根據它的文檔read-from-string可以解析文字值列表。 您遇到的問題是 NetLogo 列表文字必須有方括號才能打開和關閉,根據編程指南的常量列表部分 因此,您需要做的就是將[]添加到用戶的輸入中。

to test
  let s "0.5 0.2 0 0.2 0.5"
  let l read-from-string (word "[" s "]")
  show l
  show item 2 l
end

Output:

observer> test
observer: [0.5 0.2 0 0.2 0.5]
observer: 0

不過,我要提醒的是,用戶很容易輸入不同格式的數字,例如0, 2, 3, 5.0 ,使用逗號分隔值。 檢查轉換是否有效是明智的,因為您從失敗的read-from-string中獲得的錯誤消息可能對 model 用戶沒有幫助。

查看 CSV 擴展的“csv:from-string”原語。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM