2011-01-11 98 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> 
    

    因此,我可以搜索該項目以查看它是否在列表中,並且同樣顯示該元素缺失。

    相關問題