2011-01-11 59 views
3

以下功能项目的一个新的列表与旧的和发现的差异:已经从旧的列表中删除添加到新名单 如何比较两个列表并找出它们之间的差异?

  • 项目

    1. 项目(不存在的原始列表)。

    我写了两个循环来实现这一点,他们产生了以下的输出:

    oldItems = "an, old, list" ---> Items To Delete: 'an,old'

    newItems = "a, new, list" ---> Items To Create: '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); 
    } 
    
  • 回答

    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> 
    
    +0

    亚伦,这很棒,谢谢。我认为这对我来说将会非常有用。然而,就我的目的而言,我认为我将使用一个循环,并使用Ray提到的ListFind()函数。我认为你的UDF很棒,但在这种情况下这有点矫枉过正。感谢演示! – Mohamad 2011-01-11 13:17:04

    +0

    不用担心。但是,我确实回答了你的问题:) – 2011-01-11 13:44:34

    0

    2循环几乎做同样的事情,唯一的区别是列表已交换的地方。完全不需要。你只需要检查一个方法;旧 - >新。而不是周围的其他人(旧< - 新)。

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

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

    +0

    ziga,事情是,我需要确定已添加(创建它们)的项目以及已删除的项目,以删除它们......我想不到如果不使用两个循环... – Mohamad 2011-01-11 12:59:39

    3

    答案得到正确的匹配是使用ListFind()功能用分隔符,而不是ListContains()

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

    分隔符是必需的,否则功能将尝试与整个字符串相匹配。

    虽然没有答案的重构。

    2

    你尝试搜索CFLib.org?有多个列表功能,其中包括找出差异的功能。至于你的子串问题,请阅读ListContains上的文档。这是它应该如何工作的。改为尝试ListFind或ListFindNoCase。

    3

    上有cflib.org 3层名单的UDF:

    列表比较 - http://cflib.org/udf/listCompare - 比较一个列表对另一个发现在没有在第二列表中存在的第一个列表中的元素。与相同名称的自定义标签执行相同的功能。

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

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

    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

    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> 
    

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

    相关问题