如何比较两个列表并找出它们之间的差异?

时间:2011-01-11 12:24:28

标签: string list coldfusion refactoring

以下函数将新项目列表与旧项目列表进行比较并找出差异:

  1. 已从旧列表中删除的项目
  2. 添加到新列表中的项目(不在原始列表中)。
  3. 我写了两个循环来实现这一点,他们产生了以下输出:

      

    oldItems =“an,old,list”--->要删除的项目:'an,old'

         

    newItems =“a,new,list”--->要创建的项目:'new'

    第一个问题a应显示在要创建的项目中,但我相信因为它是an的子字符串,所以它不会被拾取。

    第二个问题(?)是我做两个循环似乎效率低下。代码可以重构吗?

    public function testList() hint="Compares two lists to find the differences."
    {
        local.oldItems = "a, new, list";
        local.newItems = "an, old, list";
        local.toDelete = "";
        local.toCreate = "";
    
        // Loop over newItems to find items that do not exist in oldItems 
        for (local.i = 1; local.i LTE ListLen(local.newItems, ", "); local.i++)
        {
            if (! ListContains(local.oldItems, ListGetAt(local.newItems, local.i, ", ")))
            {
                local.toCreate = ListAppend(local.toCreate, ListGetAt(local.newItems, local.i, ", "));
            }
        }
    
        // Loop over old items to find items that do not exist in newItems
        for (local.i = 1; local.i LTE ListLen(local.oldItems, ", "); local.i++)
        {
            if (! ListContains(local.newItems, ListGetAt(local.oldItems, local.i, ", ")))
            {
                local.toDelete = ListAppend(local.toDelete, ListGetAt(local.oldItems, local.i, ", "));
            }
        }
    
        writeDump(var="Items To Delete: '" & local.toDelete & "'");
        writeDump(var="Items To Create: '" & local.toCreate & "'", abort=true);
    }
    

7 个答案:

答案 0 :(得分:5)

是的,我相信你可以重构你的代码。

我更喜欢使用数组函数,因为它完全匹配(包括大小写)。这种方法确保“a”被选为列表之间的差异。

希望这会有所帮助:

<cfscript>
    oldList = "an, old, list";
    newList = "a, new, list";

    result = compareLists(oldList, newList);

    writeDump(result);

    // -------------------------------------------------------------------------

    public struct function compareLists (
        required string listA,
        required string listB
    ){

        local.a = listToArray(arguments.listA, ',');
        local.b = listToArray(arguments.listB, ',');

        local.itemsNotInListB = [];
        local.itemsNewInListB = [];

        // Compare all items in 'list A' to 'list B'
        for (local.item in local.a) {
            if (!arrayContains(local.b, local.item))
            {
                arrayAppend(local.itemsNotInListB, local.item);
            }
        }
        // Compare all items in 'list B' to 'list A'
        for (local.item in local.b) {
            if (!arrayContains(local.a, local.item))
            {
                arrayAppend(local.itemsNewInListB, local.item);
            }
        }

        return {
             newItems = local.itemsNewInListB
            ,deletedItems = local.itemsNotInListB
        };
    }
</cfscript>

答案 1 :(得分:3)

获得正确匹配的答案是使用带有分隔符的ListFind()函数而不是ListContains()

if (! ListFind(local.oldItems, ListGetAt(local.newItems, local.i, ", "), ", ")) {}

分隔符是必需的,否则函数将尝试匹配整个字符串。

但重构没有答案。

答案 2 :(得分:3)

cflib.org上有3个列表UDF:

列表比较 - http://cflib.org/udf/listCompare - 将一个列表与另一个列表进行比较,以查找第一个列表中第二个列表中不存在的元素。执行与同名自定义标记相同的功能。

列表差异 - http://cflib.org/udf/ListDiff - 比较两个列表并返回两个列表中未出现的元素。

List Diff Dup - http://cflib.org/udf/ListDiffDup - 此函数比较两个列表,并返回一个包含两个输入列表之间差异的新列表。此函数与ListDiff不同,因为它将列表中的重复元素视为不同的元素。

答案 3 :(得分:3)

说真的,不要重新发明轮子。使用Java列表或集合,ColdFusion在JVM上运行:

<cfscript>
oldItems = "an, old, list"; //Items To Delete: 'an,old'
newItems = "a, new, list"; //Items To Create: 'a,new'
// ArrayList could be HashSet if items in both lists are expected to be unique
oldItems = createObject("java", "java.util.ArrayList").init(listToArray(oldItems, ", "));
newItems = createObject("java", "java.util.ArrayList").init(listToArray(newItems, ", "));

itemsToDelete = createObject("java", "java.util.HashSet").init(oldItems);
itemsToDelete.removeAll(newItems);

itemsToCreate = createObject("java", "java.util.HashSet").init(newItems);
itemsToCreate.removeAll(oldItems);
</cfscript>

<cfoutput>
itemsToDelete: #listSort(arrayToList(itemsToDelete.toArray()),"textNoCase")#<br /><!--- an,old --->
itemsToCreate: #listSort(arrayToList(itemsToCreate.toArray()),"textNoCase")#<!--- a,new --->
</cfoutput>

奖励here's a link to Java code I drew my example from

答案 4 :(得分:2)

您是否尝试过搜索CFLib.org?有多个列表功能,包括一个查找差异。至于子字符串的问题,请阅读ListContains上的文档。这就是它应该如何工作。请尝试使用ListFind或ListFindNoCase。

答案 5 :(得分:1)

<cfset strListTupla = "SKU,CANTIDAD,VENTA">
<cfset strListSend = "CANTIDAD,SKU">

<cfset strListSend = ListSort(strListSend, "textnocase", "asc")>
<cfset strListTupla = ListSort(strListTupla, "textnocase", "asc")>

<cfset strListTupla = ListToArray (strListTupla)>
<cfloop index="j" from="1" to="#Arraylen(strListTupla)#">
    <cfoutput>
    <cfif NOT ListFind(strListSend, strListTupla[j])>
        Not Found #strListTupla[j]#
    </cfif><br/>
    </cfoutput>
</cfloop>

我可以搜索该项目以查看它是否在列表中,同样显示该元素缺失。

答案 6 :(得分:0)

2个循环实际上做同样的事情,唯一的区别是列表已交换位置。完全没必要。你只需要检查一种方式;老 - &gt;新。不是其他方面(Old&lt; - New)。

创建2个列表的实例并通过一个循环发送它们,在那里检查旧列表是否包含与任何新项目相等的项目。

我不知道for循环有多好用于此目的,因为旧列表中的local.i可以是索引[7],并且您需要在新索引中检查的完全相同的项可以是索引[3]在可能的变化之后。