Arrays 如何从Coldfusion数组中删除重复值?

Arrays 如何从Coldfusion数组中删除重复值?,arrays,coldfusion,duplicates,Arrays,Coldfusion,Duplicates,我有一个函数,它接收一个标签字符串。为了单独保存标记,函数将字符串转换为数组: this.tags=listToArray(this.tags,“,”) 如何在存在重复值的情况下删除重复值?从列表中删除重复值的简单方法是首先将列表转换为结构,然后将结构转换为数组。但是,如果列表中项目的顺序很重要,这可能不合适,因为结构中的元素将被排序 如果项的顺序很重要,则需要手动构建数组,而不是使用listToArray功能 <!--- CF9 ---> <cfset tags = "app

我有一个函数,它接收一个标签字符串。为了单独保存标记,函数将字符串转换为数组:

this.tags=listToArray(this.tags,“,”)


如何在存在重复值的情况下删除重复值?

从列表中删除重复值的简单方法是首先将列表转换为结构,然后将结构转换为数组。但是,如果列表中项目的顺序很重要,这可能不合适,因为结构中的元素将被排序

如果项的顺序很重要,则需要手动构建数组,而不是使用listToArray功能

<!--- CF9 --->
<cfset tags = "apples,oranges,bananas,pears,APPLES" />
<cfset tagArray = arrayNew(1) />

<cfloop list="#tags#" index="tag" delimiters=",">
    <cfif not ArrayFindNoCase(tagArray,tag)>
        <cfset arrayAppend(tagArray, tag) />
    </cfif>
</cfloop>

我喜欢使用Java来完成这类任务:

<cfset tags = "apples,oranges,bananas,pears,apples" />

<cfset tagsArray = createObject("java", "java.util.HashSet").init(ListToArray(tags)).toArray() />

<cfdump var="#tags#" />
<cfdump var="#tagsArray#" />


唯一的问题是它考虑了案例,所以认为“苹果”和“苹果”是不同的东西(这在技术上是肯定的,取决于你的系统很可能是不同的)。反过来说,首先要降低列表中所有内容的大小写。

基于Jason Haritou的思想,但您可以在纯CF中使用Struct!(密钥匹配不区分大小写)


然而,对于小列表,我更喜欢Antony的解决方案。

CFLib上有几个UDF可以实现这一点,ArrayyDiff(http://www.cflib.org/udf/arrayDiff)和ArrayCompare(http://www.cflib.org/udf/arrayCompare)

嗯,,
larry

我只需要对一个非常大的列表(5k+个条目)进行重复数据消除,然后找到了一种比使用循环快得多的方法。我觉得有必要分享

  • 将列表转换为数组(您已经有了数组,所以跳过)
  • 使用queryNew(“”
  • 使用步骤1中的数组将列添加到该查询
  • 查询不同的值
    从此查询中选择不同的项目
  • 将结果转换为列表
  • 将此列表转换回数组是一个简单的步骤
  • 为了便于使用,我将其写入函数:

    <cffunction name="deDupList" output="no" returntype="string">
        <cfargument name="thisList" required="yes">
        <cfargument name="thisDelimeter" required="yes" default=",">
        <cfset var loc = StructNew()>
    
        <cfset loc.thisArray = ListToArray(thisList,thisDelimeter)>
        <cfset loc.thisQuery = QueryNew("")>
        <cfset loc.temp = QueryAddColumn(loc.thisQuery,"items","varChar",loc.thisArray)>
        <cfquery name="qItems" dbtype="query">
            SELECT DISTINCT items FROM loc.thisQuery
        </cfquery>
        <cfset loc.returnString = ValueList(qItems.items)>
        <cfreturn loc.returnString>
    </cffunction>
    
    
    从loc.thisQuery中选择不同的项目
    
    我将其与其他几种方法进行了对比,以下是以毫秒为单位的结果:
    循环检查>1个实例的列表:6265
    使用Henry的结构方法:2969
    上述方法:31

    Jason的方法:30

    只需将数组放入结构中,然后将其复制回数组;)


    在Coldfusion 10或Railo 4中,您可以使用:

    uniq()
    的一个优点是,它允许您在必要时传递转换函数


    注意:我写了下划线.cfc

    ,因为您实际上是从一个字符串/列表开始,然后将其转换为一个数组,所以您可以在将字符串转换为数组之前传递该字符串。在Coldfusion 10中引入了ListRemovedDuplicates;输入参数是(list,delimiter=“,”,ignoreCase=FALSE)

    如果您实际上是从一个数组开始,那么您需要先将它转换为一个列表,然后再转换回来

    this.tags = listToArray(listRemoveDuplicates(arrayToList(arrayInput),", ",TRUE) );
    

    让jason的答案更进一步,这里有一个
    arrayDistinct
    函数

    function arrayDistinct (required array data) {
        var output = arrayNew(1);
        output.addAll(createObject("java", "java.util.HashSet").init(arguments.data));
        return output;
    }
    

    您可以在这里进行测试:

    Java中提供的“set”抽象数据类型是专门为解决这类问题而设计的。谢谢。你是否做过任何测试/知道你的头顶是否比将值循环到ColdFusion结构中更快?@Mohamad-从绝对速度的角度来看,我猜HashSet会更快。但是除非你处理的是庞大的列表,否则差异通常很小。我通常选择做正确工作的方法,只有当它成为一个问题时,我才会担心速度。这个解决方案的美妙之处在于它只需要一行代码!在我的例子中,我需要找出coldfusion查询中的特定字段是否有多个唯一值。虽然这里列出的其他解决方案也能起作用,但这一行代码使我的代码非常简单:
    if(ArrayLen(createObject(“java”,“java.util.HashSet”).init(cfQuery[colName]).toArray())GT 1)
    Jason,谢谢你的代码。从另一个系统中提取数据后,我有一个具有重复值的结构数组。我能够通过HashSet传递数组,最终得到一个重复数据消除的数组集?结构不允许以任何方式复制值,所以在这里使用条件不是有点多余吗?(编辑)我可以看出循环是多么缓慢。但我很惊讶你说杰森的方法很慢。对我来说,这是闪电般的快,超过10公里的物品。我甚至作弊,把结果传回一个向量,让CF高兴。我在执行Jason的方法时把我的基准脚本弄乱了,愚蠢的错误。你说得对,他的速度真他妈的快,纠正了我的基准测试结果。谢谢,谢谢。我可能会选择
    HashSet
    。但有趣的是,QoQ比我预期的要快。代码转储不是答案。请编辑你的答案,解释一下这个代码是什么,它是如何工作的,以及它是如何回答这个问题的。只要阅读它,就会清楚发生了什么。提示:
    ListRemovedDuplicates
    是用ColdFusion 10添加的。不要在早期版本上尝试。
    this.tags = listToArray(listRemoveDuplicates(arrayInput,", ",TRUE));
    
    this.tags = listToArray(listRemoveDuplicates(arrayToList(arrayInput),", ",TRUE) );
    
    function arrayDistinct (required array data) {
        var output = arrayNew(1);
        output.addAll(createObject("java", "java.util.HashSet").init(arguments.data));
        return output;
    }