Как я могу сравнить два списка и найти различия между ними? - PullRequest
3 голосов
/ 11 января 2011

Следующая функция сравнивает новый список элементов со старым и находит различия:

  1. Элементы, которые были удалены из старого списка
  2. Элементы, которые были добавлены вновый список (отсутствует в исходном списке).

Я написал два цикла для достижения этой цели, и они дали следующий вывод:

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 ]

5 голосов
/ 11 января 2011

Да, я полагаю, вы можете изменить свой код.

Я предпочитаю использовать функции массива, так как они точно соответствуют (включая регистр). Этот метод гарантирует, что «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>
3 голосов
/ 11 января 2011

Серьезно, не изобретай велосипед. Используйте списки или наборы 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>

В качестве бонуса вот ссылка на код Java, мой пример взят из .

3 голосов
/ 11 января 2011

На cflib.org есть 3 списка пользовательских функций:

.

Сравнение списков - http://cflib.org/udf/listCompare - Сравнивает один список с другим, чтобы найти элементы в первом списке, которые не существуют во втором списке. Выполняет ту же функцию, что и пользовательский тег с тем же именем.

Список различий - http://cflib.org/udf/ListDiff - Сравнивает два списка и возвращает элементы, которые не отображаются в обоих списках.

List Diff Dup - http://cflib.org/udf/ListDiffDup - Эта функция сравнивает два списка и возвращает новый список, содержащий разницу между двумя списками ввода. Эта функция отличается от ListDiff тем, что обрабатывает дублирующиеся элементы в списках как отдельные элементы.

3 голосов
/ 11 января 2011

Ответом на получение правильных совпадений является использование функции ListFind() с разделителем вместо ListContains():

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

Разделитель необходим, иначе функция будет пытаться сопоставить всю строку.

Ответа за рефакторинг пока нет.

2 голосов
/ 11 января 2011

Вы пытались найти CFLib.org?Есть несколько функций списка, в том числе одна, чтобы найти различия.Что касается ваших проблем с подстроками, прочитайте документацию на ListContains.Вот как это должно работать.Вместо этого попробуйте ListFind или ListFindNoCase.

1 голос
/ 22 января 2013
<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>

С этим я могу искать элемент, чтобы увидеть, есть ли он в списке или нет, и также показать, что элемент отсутствует.

0 голосов
/ 11 января 2011

2 цикла практически одинаковы, единственное отличие состоит в том, что списки поменялись местами. Совершенно ненужно. Вам нужно проверить только один способ; Старый -> Новый. И наоборот тоже (Старый <- Новый). </p>

Создайте экземпляр из 2 списков и отправьте их через один цикл, где вы проверяете, содержит ли старый список элемент, равный любому из новых элементов.

Я не знаю, насколько хорош цикл for для этой цели, так как local.i в старом списке может быть index [7], и точно такой же элемент, который нужно проверить в новом, может быть index [3] после возможных изменений.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...