简体   繁体   English

如何解析 Netlogo 中的字符串?

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

Context语境

For my model I would like to have an input where the user can enter a series of values.对于我的 model,我想要一个输入,用户可以在其中输入一系列值。

Eg例如

在此处输入图像描述

What I would like to have from the input shown above is a list of five numbers, eg [0.5 0.2 0 0.2 0.5] , so I can then use the numbers that they enter for some calculations.我想从上面显示的输入中得到一个包含五个数字的列表,例如[0.5 0.2 0 0.2 0.5] ,因此我可以使用他们输入的数字进行一些计算。

The problem问题

Unfortunately, having an input set up like above will spit out "0.5 0.2 0 0.2 0.5" if I set the type to be a string.不幸的是,如果我将类型设置为字符串,那么像上面这样设置输入会吐出"0.5 0.2 0 0.2 0.5" If I set the type to numeric, it will only allow a single number to be entered.如果我将类型设置为数字,它将只允许输入一个数字。

So, how can I parse the string the basis of a space (ie " ")?那么,如何以空格为基础(即“”)解析字符串? I am open to alternatives too, although I would prefer to keep it in Netlogo (eg not reading in a text file of values) to make it easier to change, as it is something that I suspect will get played around with a lot.我也对替代品持开放态度,尽管我更愿意将其保留在 Netlogo 中(例如,不读取值的文本文件)以使其更容易更改,因为我怀疑它会被很多人玩弄。

What I have tried我试过的

I have tried using read-from-string , but it also doesn't like a series of numbers entered like above.我曾尝试使用read-from-string ,但它也不喜欢像上面那样输入一系列数字。 I also attempted to use the explode function from the string extension ( https://github.com/NetLogo/String-Extension ), but my version of Netlogo (6.2.0) did not like the API from that extension and wouldn't allow me to use it.我还尝试使用字符串扩展名( https://github.com/NetLogo/String-Extension )中的explode function ,但我的 Netlogo 版本(6.2.0)不喜欢来自该扩展名的 ZDB974238714CAtADE634 的 ZDB974238714CAtADE634请允许我使用它。

I am very new to NetLogo, so sorry if my question is silly or I have not made something clear!我对 NetLogo 很陌生,如果我的问题很愚蠢或者我没有说清楚,很抱歉!

You can do it with a combination of position , substring , read-from-string and fput .您可以结合positionsubstringread-from-stringfput

This is the workflow:这是工作流程:

  1. Create a loop that goes on as long as the string contains more than one number (= as long as it contains at least one space, checked using position " " string );创建一个循环,只要字符串包含多个数字(= 只要它包含至少一个空格,使用position " " string检查);
  2. Extract a substring that goes from the first character to the first space excluded (done with substring );提取从第一个字符到排除的第一个空格的 substring (使用substring完成);
  3. Read that substring as a numeric value (with read-from-string ) and add it to list-of-numbers (with fput );将 substring 作为数值读取(使用read-from-string )并将其添加到list-of-numbers (使用fput );
  4. Drop the first number in the string (using position " " string , repeat and but-first ) and start the loop again;删除字符串中的第一个数字(使用position " " stringrepeatbut-first )并再次开始循环;
  5. When the loop condition evaluates as FALSE it means that only one number is left in the string.当循环条件评估为FALSE时,这意味着字符串中只剩下一个数字。 Add that last number (ie the whole remaining string) to list-of-numbers outside the loop, and it's all done.将最后一个数字(即整个剩余的字符串)添加到循环外的list-of-numbers ,这一切都完成了。

The procedure below is a reporter procedure that executes this workflow and reports a list of values as read from the string (it only needs a user-string input box in the Interface):下面的过程是一个报告过程,它执行这个工作流并报告从字符串中读取的值列表(它只需要界面中的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

So for example:例如:

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]


The procedure I posted above is the condensed version of the initial code I made, that I am leaving here below abundantly commented:我上面发布的过程是我制作的初始代码的精简版,我将在下面留下大量评论:

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

As per the docs on it , read-from-string can parse a list of literal values.根据它的文档read-from-string可以解析文字值列表。 The issue you are having is that a NetLogo list literal must have square brackets to open and close, as perthe Constant Lists section of the Programming Guide .您遇到的问题是 NetLogo 列表文字必须有方括号才能打开和关闭,根据编程指南的常量列表部分 So all you need to do is add [ and ] to your user's input.因此,您需要做的就是将[]添加到用户的输入中。

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: Output:

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

I would caution, though, that it would be very easy for users to enter numbers with a different format, like 0, 2, 3, 5.0 , using commas to separate values.不过,我要提醒的是,用户很容易输入不同格式的数字,例如0, 2, 3, 5.0 ,使用逗号分隔值。 A check that the conversion actually worked would be wise, as the error message you'd get from the failed read-from-string probably wouldn't be helpful to the model user.检查转换是否有效是明智的,因为您从失败的read-from-string中获得的错误消息可能对 model 用户没有帮助。

Check out the CSV extension's "csv:from-string" primative.查看 CSV 扩展的“csv:from-string”原语。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM