当列表以逗号开头时在列表中查找特定实例

Finding specific instance in a list when the list starts with a comma

我正在上传电子表格并将电子表格列标题映射到我数据库中的列标题。电子邮件列是唯一需要的列。在下面的 StringB 中,,,, 只是表示列是 skipped/ignored。

我的问题是这样的:

我有一个来自电子表格的文本字符串 (StringA),我需要在另一个与我的数据库匹配的文本字符串 (StringB) 中找到它(这不是真正的值,只是为了简单说明我的问题所以希望这是清楚的)。

字符串A:YR,MNTH,ANNIVERSARIES,FIRSTNAME,LASTNAME,EMAIL,NOTES
StringB: ,YEAR,,MONTH,LastName,Email,Comments <-- 这个列表是动态的

MNTHMONTH 是故意不同的;

excelColumnList = 'YR,MNTH,ANNIV,FIRST NAME,LAST NAME,EMAIL,NOTES';  
mappedColumnList=  ',YEAR,,MONTH,,First Name,Last Name,Email,COMMENTS';  
mappedColumn= 'Last Name';    

local.index = ListFindNoCase(mappedColumnList, mappedColumn,',', true);

local.returnValue = "";

if ( local.index > 0 )

    local.returnValue = ListGetAt(excelColumnList, local.index);

writedump(local.returnValue);   // dumps "EMAIL" which is wrong

我遇到的问题是当 StringB 以 , returns 开头时返回的索引是错误的索引值,这会影响以后的映射。如果 StringB 以单词开头,则该过程完美运行。当 StringB 以 , 开头时,是否有更好的方法来获取索引?

我也尝试使用 listtoarray 然后 arraytolist 来清理它,但索引仍然关闭,我不能可靠地只向索引添加 +1 来识别列表中的正确项目.

另一方面,我正在考虑这个 mappedColumnList = right(mappedColumnList,len(mappedColumnList)-1) 来删除前导 ,,它仍然会抛出我的索引值,但我可以通过在索引中添加 1 来解决这个问题,这出现了乍一看是可靠的。只是担心这是一种黑客行为。

有什么建议吗?

https://cfdocs.org/listfindnocase

这是一个 cfgist:https://trycf.com/gist/4b087b40ae4cb4499c2b0ddf0727541b/lucee5?theme=monokai

已更新 我使用 EDIT #1 接受了答案。我还在这里添加了评论:

识别并删除列表中的“,”(如果它是第一个字符)。

编辑:更改为 while 循环以识别多个前导“,”s。

尝试:

while(left(mappedColumnList,1) == ",") {
    mappedColumnList = right( mappedColumnList,(len(mappedColumnList)-1) ) ;
}

https://trycf.com/gist/64287c72d5f54e1da294cc2c10b5ad86/acf2016?theme=monokai

编辑 2: 甚至更好,如果您不介意回到 Java(和一点正则表达式),您可以完全跳过循环。超级高效。

mappedColumnList =  mappedColumnList.replaceall("^(,*)","") ;

然后完全放弃 while 循环。

https://trycf.com/gist/346a005cdb72b844a83ca21eacb85035/acf2016?theme=monokai

<cfscript>
excelColumnList = 'YR,MNTH,ANNIV,FIRST NAME,LAST NAME,EMAIL,NOTES';
mappedColumnList=  ',,,YEAR,MONTH,,First Name,Last Name,Email,COMMENTS';  
mappedColumn= 'Last Name';    

mappedColumnList =  mappedColumnList.replaceall("^(,*)","") ;

local.index = ListFindNoCase(mappedColumnList, mappedColumn,',', true);

local.returnValue = ListGetAt(excelColumnList,local.index,",",true) ;

writeDump(local.returnValue);
</cfscript>

正则表达式的解释 ^(,*):

  • ^ = 从字符串的开头开始。
  • () = 捕获这组字符
  • ,* = 文字逗号和所有连续重复。

所以^(,*)说,从字符串的开头开始并捕获所有连续的逗号,直到到达下一个不匹配的字符。然后 replaceall() 只是用空字符串替换那组匹配的字符。

编辑 3: 我修正了我原来答案中的一个拼写错误。我只使用了一个列表。

writeOutput(arraytoList(listtoArray(mappedColumnList))) 将去掉您的前导逗号,但这是因为它会在成为数组之前删除空元素。这会使您的索引失效,因为您的原始 mappedColumnList 字符串中有一个空元素。后面的字符串函数将读取和索引该空元素。所以,为了让你的索引像你看到的那样工作,你要么需要确保你的 Excel 和 db 列总是以相同的顺序排列,要么你必须为每个列创建某种映射列名称,然后对您需要使用的字符串执行 ListGetAt()

默认情况下,许多 CF 列表函数会忽略空元素。向这些函数添加了一个标志,以便您可以禁用此行为。如果默认情况下有字符串 ,,1,2,3 listToArray 会考虑 3 个元素,但 listToArray(listVar, ",", true) 会 return 5,前两个为空字符串。 ListGetAt 具有相同的 "includeEmptyValues" 标志,因此当该标志设置为 true 时,您的代码应该能够始终如一地工作。