以下函数将新项目列表与旧项目列表进行比较并找出差异:
我写了两个循环来实现这一点,他们产生了以下输出:
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);
}
答案 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>
答案 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]在可能的变化之后。