【问题标题】:trying to get the value of the struct inside an array试图获取数组中结构的值
【发布时间】:2020-12-01 11:39:16
【问题描述】:

在 java 或 cfm 中寻找单行代码,我不需要循环遍历 te 结构数组以使用 te structfind 从中获取值。

现在正在看,

Coldfusion - How to loop through an Array of Structure and print out dynamically all KEY values?

我可以在哪里循环并获取键匹配的值

但尝试检查是否可以完成这样的事情

<cfset myvalue = structfindvaluefromAnything(myarrayofstruct,"infor")>

【问题讨论】:

  • 对我来说您期望返回的内容并不明显,也许您可​​以包含示例输入数据及其预期返回值?您是在尝试匹配键名的存在,还是匹配值而不考虑键名?如果您有一个包含 10 个结构的数组,其中 5 个结构包含匹配项,您希望返回哪种格式?
  • 如果他们中的任何一个具有“infor”的值,它应该返回我,第一个实例 find 将起作用,无论它是否出现在 other 中,如果它找到任何“infor”的价值,我的目的就解决了
  • 那么你想返回包含任何值为“infor”的键的整个第一个结构吗?还是要返回任何名为“infor”的键的第一个值?
  • 现代 ColdFusion 的一个很酷的地方是能够使用闭包而不是循环。快得多。

标签: arrays coldfusion cfml lucee


【解决方案1】:

我相信可用于此的功能几乎正是您所希望的......

StructFindValue(struct, value [, scope])

在嵌套数组、结构和其他元素的子结构中递归搜索其值与 value 参数中的搜索键匹配的结构。

返回一个数组,其中包含值与搜索键值匹配的结构键。如果没有找到,则返回一个大小为 0 的数组。

【讨论】:

  • 请注意,您必须将结构传递给 StructFindValue();问题中的结构数组会引发错误。尽管我想您可以将结构数组填充到另一个结构中,然后向下遍历到匹配的 owner
【解决方案2】:

如果您真的想在一行中完成,那么您可以将ArrayFilter()StructFindValue() 结合使用。

改编自 ArrayFilter 的 Adob​​e 文档 - https://helpx.adobe.com/coldfusion/cfml-reference/coldfusion-functions/functions-a-b/arrayfilter.html - 类似这样:

<cfscript>
     superheroes=[
           {"name":"Iron Man","member":"Avengers"},
           {"name":"Wonder Woman","member":"Justice League"},
           {"name":"Hulk","member":"Avengers"},
           {"name":"Thor","member":"Avengers"},
           {"name":"Aquaman","member":"Justice League"}
     ];
 
    avengers=ArrayFilter(superheroes,function(item){ 
        return ArrayLen(StructFindValue( item, "Avengers"));
    });
    writeDump(var=avengers, label="all matches");

    writeDump(var=ArrayLen(avengers) ? avengers[1] : "Not found", label="first match only");

    writeDump(var=structFindValue({"a":superheroes}, "Avengers", "all"), label="without arrayFilter");
</cfscript>

【讨论】:

    【解决方案3】:

    我喜欢 Sev 的方法。我会稍微改变一下

    <cfscript>
         superheroes=[
               {"name":"Iron Man","member":"Avengers"},
               {"name":"Spider-Man","member":"Avengers"},
               {"name":"Wonder Woman","member":"Justice League"},
               {"name":"Hulk","member":"Avengers"},
               {"name":"Thor","member":"Avengers"},
               {"name":"Aquaman","member":"Justice League"}
         ];
     
         avengers = superheroes.filter(function(item) { 
            return item.member ==  "Avengers";
        });
         writeDump(avengers);
    </cfscript>
    

    【讨论】:

    • 这实际上是我从中提取的 Adob​​e 示例 - 尽管使用 array.filter() 而不是 ArrayFilter() - 但是我调整它的原因是因为 OP 的问题并不意味着我们知道哪个我们在其中搜索匹配项的键名 - 因此 cmets 要求澄清。
    • 如果这是 Lucee 5,你也可以把它缩短很多并使用箭头函数。 avengers = superheroes.filter( (item) =&gt; ( item.member == pickme ) ); 其中pickme 是您传入的过滤值。
    • @SevRoberts 出于所有意图和目的,.filter() 在应用于数组时与ArrayFilter() 相同。
    • 这是我的要点cffiddle.org/app/…
    • 根据你的主旨,我想我明白你在追求什么。另一个答案来了。
    【解决方案4】:

    根据您在上面提供的要点 (https://cffiddle.org/app/file?filepath=3e26c1ac-d5db-482f-9bb2-995e6cabe704/49b3e106-8db9-4411-a6d4-10deb3f8cb0e/24e44eba-45ef-4744-a6e6-53395c09a344.cfm),我认为您已经稍微澄清了您的期望。

    在您的要点中,您说您希望能够搜索结构数组并找到具有"name" 键且值为"form" 的行。然后,您想要获取与数组行中的该结构关联的 "value" 键的值。如果没有value,则返回0

    您希望能够在一行代码中做到这一点,而上述答案确实做到了。我的回答基本上建立在这些之上。

    如前面的答案所示,您仍然希望使用闭包函数来过滤最终输出。这些速度非常快,基本上是为了做你想做的事情。

    我使用的 Fiddle 在这里:https://cffiddle.org/app/file?filepath=b3507f1d-6ac2-4900-baed-fb3faf5a3b3a/e526afc2-bb85-4aea-ad0e-dcf38f52b642/75d88d2b-f990-44c1-9d9f-22931bf9d4d7.cfm

    我已经用这个做了两件事。

    首先,我的工作就像您希望为您的过滤值遇到多个记录一样,然后将它们转换为逗号分隔的列表。如果您需要其他结构,可以修改我代码中的reduce() 函数来处理。

    其次,我的工作就像您希望只遇到一个过滤记录一样,只返回一个值。

    我做的第一件事,这两种方法基本相同,与前面的答案基本相同,就是过滤原始数组以获得所需的值。

    这样做是这样的:

    myResult = originalArray.filter( 
        function(itm){ 
            return itm?.name=="form";   /// ?. = safe-navigation operator.
        } 
    )
    

    为了清楚起见,我将它分成多行。

    这将返回一个由过滤后的行组成的新结构数组。

    但是您想获取这些记录并从这些行中返回 "value"(如果没有值,则默认为 0。您可以使用 reduce() 执行此操作。

    commaDelimitedValue = 
        myResult.reduce( 
            function(prev,nxt) { 
                return prev.listappend( ( nxt.value.len() ? nxt.value : 0 ) ) ;
            }
            , ""   /// Initialization value 
        ) ;
    

    同样,这可以写在一行中,但为了清楚起见,我包含了换行符。

    reduce() 函数本质上只是将您的输入减少为单个值。它遵循.reduce( function( previousValue, nextValue ){ return .... },&lt;initializationValue&gt;) 的格式,其中,在第一次迭代中,initializationValue 被替换为previousValue,然后previousValue 成为该迭代的结果。 nextValue 实际上是您将从中得出结果的当前迭代。

    更多信息:https://coldfusion.adobe.com/2017/10/map-reduce-and-filter-functions-in-coldfusion/

    在我的假设中,您可能会从您的filter() 返回多行。您获取这些行并将value 附加到逗号分隔的列表中。因此,您最终会得到类似 20,10,0,0 的结果 - 代表过滤结果中的 4 行。

    我还检查value 的长度,如果它是空字符串,则默认为0。上面,我说过你可以只使用 Elvis 运算符 (:?),但这不适用于像空字符串这样的简单值。 Elvis 与 NULLs 一起使用,早期的数组确实有。

    要回到一行,您可以链接这两个函数。所以你最终得到:

    myFinalResult =  
        myOriginalArray.filter( 
            function(itm){ 
                return itm?.name=="form";
            } 
        )
        .reduce(   
            function(prev,nxt) { 
                return prev.listappend( ( nxt.value.trim().len() ? nxt.value : 0 ) ) ;
            }
            , ""
        ) 
    ;
    

    同样,该代码做了很多工作,但它本质上仍然是一行。最终结果将再次类似于 "20,10,0,0" 4 行,其中 2 默认为 0

    如果您只希望您的过滤器返回一行,或者您只需要一个值,您可以稍微简化一下。

    myFinalResult = myOriginalArray.filter( function(itm){ return itm?.name=="fm" && (itm?.value.trim().len()>0) ; } )[1]["value"] ?: 0 ;
    

    有了这个,我又回到了使用我之前的猫王技巧来默认没有value的行,因为我正在过滤掉带有空字符串"value""form"结构。 &amp;&amp;AND 相同。从技术上讲,这个 CAN 从原始数组中过滤了不止一行,但[1] 只会从过滤后的行中选择第一行。它也不需要使用reduce()。如果过滤的行不止一行,则每次迭代都会覆盖前一个。

    这将返回一个简单的单一值,类似于 42 - 这是数组中最后过滤的值,因为它会覆盖前一行的值。

    我的 Fiddle (https://cffiddle.org/app/file?filepath=b3507f1d-6ac2-4900-baed-fb3faf5a3b3a/e526afc2-bb85-4aea-ad0e-dcf38f52b642/75d88d2b-f990-44c1-9d9f-22931bf9d4d7.cfm) 有一些额外的 cmets,我设置了几个边缘案例来演示过滤和安全导航。


    我还想重申,如果这是 Lucee 5+ 或 ACF2018+,您可以使用箭头函数进一步缩短它。

    【讨论】:

    • 我还提醒您,如果您使用一些“特殊”词(如 "form""value")作为变量名或值,可能会导致问题。或者它可能会导致混乱,有时会更糟。 :-/
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-03
    • 1970-01-01
    • 2017-11-08
    • 1970-01-01
    • 2012-03-14
    相关资源
    最近更新 更多