How to compare two lists and find the differences between them

coldfusionlistrefactoringstring

The following function compares a new list of items to an old one and finds the differences:

  1. Items that have been deleted from the old list
  2. Items that were added to the new list (not present in the original list).

I wrote two loops to achieve this, and they produced the following output:

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

newItems = "a, new, list" —> Items To Create: 'new'

The first issue is a should show up in the items to create, but I believe because it's a substring of an it's not getting picked up.

The second issue(?) is I doing two loops seems inefficient. Can the code be refactored?

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);
}

Best Answer

Yes, I believe you can refactor your code.

I prefer to use the array functions as it does an exact match (including case). This method ensures that "a" is picked up as a difference between the lists.

Hope this helps:

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