【问题标题】:Sum up dynamic fields in list汇总列表中的动态字段
【发布时间】:2020-11-07 06:34:37
【问题描述】:

我有一个类似的列表:

<cfset list ="group 1:1; group 2:4; group a:7; group 1:3; group a:1;">

我要做的是计算(总结)第 1 组、第 2 组、第 a 组等中有多少人。现在这些字段是动态的,所以我不知道组的确切名称。

所以这个例子的最终结果是:

group 1: 4
group 2: 4
group a: 8

所以该列表只是一个示例,实际上它会随着更多组(动态名称)而变得更大。我正在使用 Coldfusion/Lucee。有人可以帮我解决这个问题吗?

【问题讨论】:

    标签: list coldfusion lucee


    【解决方案1】:

    这只是众多可能的替代方法之一。从使用查询而不是列表作为起始值开始。

    我正在做的是使用; 作为分隔符循环列表并将值添加到结构中。稍后我使用该结构循环并列出最终总数。

    <cfset list ="group 1:1; group 2:4; group a:7; group 1:3; group a:1;">
    <cfset totalStruct = {}>
    <cfloop list="#list#" item="group" delimiters=';'>
      <cfset groupName = listFirst(group, ':')>
      <cfset groupNameKey = replace(groupName, ' ', '', 'all')>
      <cfset groupValue = val(listLast(group, ':'))>
      <cfif !structKeyExists(totalStruct, groupNameKey)>
        <cfset totalStruct[groupNameKey] = {name:groupName, total=groupValue}>
      <cfelse>
        <cfset totalStruct[groupNameKey].total += groupValue>
      </cfif>
    </cfloop>
    <cfoutput>
      <ul>
        <cfloop collection="#totalStruct#" item="group">
          <li>#totalStruct[group].name# : #totalStruct[group].total#</li>
        </cfloop>
      </ul>
    </cfoutput>
    

    DEMO

    【讨论】:

      【解决方案2】:

      另一种选择是使用map 和/或reduce 闭包函数来解析您的列表。

      注意 1:我通常发现 cfscript 对于解析文本或“循环”的大多数事情要容易得多。

      注意 2:我不是循环的忠实粉丝,尤其是在大文本值周围。闭包函数的性能可能会更高。

      <cfset lst ="group 1:1; group 2:4; group a:7; group 1:3; group a:1;">
      

      首先,在函数内部使用map()

      <cfscript>
          public Struct function parseLst (required String lst) {
              var retval = {} ; //// Default return variable. 
              //// https://docs.lucee.org/reference/functions/listmap.html
              arguments.lst.listmap(    
                  function(el) {
                      var k = el.listFirst(":").ltrim() ; /// Get the "key" and strip extra leading space.
                      var v = el.listLast(":") ; /// Get the "value".
                      
                      var p = retval["#k#"]?:0 ; /// Use Elvis to default to 0 if no struct Key exists. 
                      
                      retval["#k#"] = v + p ; /// Set the value of the key. NOTE: A struck key with the same name will generally overwrite itself. We want to add it.
                  }
                  ,";" /// Specify the delimiter of the list. 
              ) ;
              
              return retval ;
          }
      
          writeDump(parseLst(lst));
      </cfscript>
      

      然后使用reduce() 而不在函数内部。

      <cfscript>
          //// https://docs.lucee.org/reference/functions/listreduce.html
          r = listReduce(lst,
              function(prev,nxt){
                  k = nxt.listFirst(":").ltrim() ;  /// Get the "key" and strip extra leading space.
                  /// To shorten it, I just skipped setting the value beforehand and just did it while setting the struct value. Same method as above.
                  prev["#k#"] = (nxt.listLast(":"))+(prev["#k#"]?:0) ; 
                  return prev ;
              }
              ,
              {}    // Initial value
              ,";"  // Delimiter
          ) ;
          
      
          writedump(r) ;
      </cfscript>
      

      两者都可以(并且可能应该)在一个函数中,然后您可以将您的列表变量发送给它。

      如果可能的话,修复原始列表以使其更易于使用可能会容易得多。

      https://trycf.com/gist/dda51d88504a625fce5548142d73edb3/lucee5?theme=monokai

      ================================================ ========

      编辑:

      使用listFirst/Last() 函数的替代方法是将“列表”转换为数组,然后使用这些部分来获取“键”和“值”。

      <cfscript>
          //// https://docs.lucee.org/reference/functions/listreduce.html
          s = listReduce(lst,
              function(prev,nxt){
                  var elem = nxt.listToArray(":") ;
                  
                  prev["#elem[1].ltrim()#"] = elem[2] + (prev["#elem[1].ltrim()#"]?:0) ;
                  return prev ;
              }
              ,
              {}    // Initial value
              ,";"  // Delimiter
          ) ;
          
      
          writedump(s) ;
      </cfscript>
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-01-08
        • 1970-01-01
        • 2018-11-05
        • 2021-10-03
        • 2022-08-18
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多