在Javascript中,ColdFusion的listFindNoCase函数有什么最快的实现方式?

5

我已经习惯了ColdFusion的列表,但有一两个情况下在Javascript中出现了逗号分隔的列表。是否有listFindNoCase('string','list')的等效方法或实现它的高性能方式?

噢,它还应该能够处理带逗号的列表项,例如: ( "Smith, John" , "Doe, Jane" , "等等..." )

这才是让我困扰的关键。


你是说你有一个类似的字符串吗?基本上是CSV字符串?还是你有一个JavaScript数组? - aquinas
有点尴尬地说,我一直在填充我的头脑与复杂的循环和可能的正则表达式字符串,而indexOf却可以直接使用!我只是假设indexOf仅适用于数组:P - eterps
我认为在JS中使用正则表达式会相当简单。当你说快的时候,是指它运行快还是你可以快速编写一个? - Henry
这个问题 不是 在 JavaScript 中寻找 ListFindNoCase(顺便说一下,它可以在 cfjs 中获得) - 它是要查找 CSV 字符串中某个项的位置,这是不同的东西。 - Peter Boughton
3个回答

4

FYI:jList的实现:https://github.com/davidwaterston/jList

不过,它无法处理带逗号的列表项,这与您的要求不符。

listFind : function (list, value, delimiter) {
    delimiter = (typeof delimiter === "undefined") ? "," : delimiter;

    var i,
        arr = list.split(delimiter);

    if (arr.indexOf !== undefined) {
        return arr.indexOf(value) + 1;
    }

    for (i = 0; i < list.length; i += 1) {
        if (arr[i] === value) {
            return i + 1;
        }
    }

    return 0;
},


listFindNoCase : function (list, value, delimiter) {
    delimiter = (typeof delimiter === "undefined") ? "," : delimiter;

    list = list.toUpperCase();
    value = String(value).toUpperCase();

    return this.listFind(list, value, delimiter);
},

3
一个相关的观察是,CF列表本身不支持分隔符字符也成为数据的一部分。你的样例“列表”是由四个元素组成的逗号分隔列表,其中包含“Smith, John”,“Doe, Jane”。为了满足您的要求,您不需要JS等效于CF的listFindNoCase(),因为listFindNoCase()实际上并没有从CF的角度来看满足您的要求,而且CF本身也没有任何原生方法能够满足您的要求。为了处理具有嵌入逗号的元素,您需要使用另一个字符作为分隔符。
说实话,CF列表有点垃圾(因为上述原因),它们只在非常平凡的情况下才有用,这种情况a)很少出现;b)无论如何都不如使用数组更好。这里要提出的一个观察是,在这里你正在询问一个高性能的解决方案:不使用基于字符串的列表将是实现高性能的第一步(这同样适用于CF和JS:CF的基于字符串的列表根本不具备高性能)。
因此,我首先的答案是:我认为您应该修改您的需求,不再使用列表,并改为使用数组。
考虑到这一点,数据是如何传输到JS的?您是否被迫使用基于字符串的列表?如果不是,请不要使用。如果您的源数据是基于字符串的列表,您是否有能力先将其转换为数组?正如我之前提到的,您在示例列表的“模式”方面遇到了一些麻烦:从CF的角度来看,逗号不能同时作为分隔符和数据。你需要编写代码来识别带引号的逗号是数据,非带引号的逗号是分隔符。您应该查找CSV解析算法来处理这种情况。
但是,如果您可以更改分隔符(比如说管道或分号或其他不会出现在数据中的字符),那么将其转换为数组就很容易了(在CF中是listToArray(),在JS中是split())。然后,您只需像其他人所说的那样使用indexOf()即可。
为了好玩,如果您被困在一个字符串中 - 假设您可以更改分隔符 - 您可以这样做:
  1. 使用indexOf()方法查找字符串中第一个匹配的子字符串的位置,您需要使用正则表达式来匹配由定界符字符分隔的子字符串,或者从字符串开头到定界符字符,或者从定界符字符到没有中间定界符字符的字符串结尾。如果必要,我可以提供此正则表达式。这仍然不会考虑列表,但我们知道它在字符串中的位置。
  2. 从原始字符串中取一个子字符串,从开头到indexOf()方法返回的位置。
  3. 在该子字符串上使用split()方法,在定界符上进行拆分。
  4. 得到的数组长度将是原始list中匹配项所在的位置。

但是我强调您不应该这样做。最好从一开始就使用数组而不是字符串。


1
你的前两段话是误导性的 - CF 没有列表!它有处理简单分隔字符串的函数,这些函数恰好使用“list”一词来指示它们所做的事情,但它们只是基本的字符串操作(当需要时非常有用)。 - Peter Boughton
这是一些过于琐碎的细节了,Peter。我想知道你为什么费心去做这件事。但无论如何:我认为其他人可能已经明白了我们在讨论什么,不需要进一步解释。谢谢。 - Adam Cameron
我进行了评论,因为这是误导性的 - 在CF中,“列表”是一个特定的事物是一个常见的误解,而实际上并非如此。提到“CF列表”有可能会导致混淆,而SO的目的通常是相反的。 - Peter Boughton

2
您可以使用indexOf.toLowerCase()结合使用。
var list = '"Smith, John" , "Doe, Jane" , "etc..."';
if(list.toLowerCase().indexOf('"Smith, John"'))

如果您需要精确匹配,例如当存在“Smithson”时仅匹配“Smith”,请使用分隔符填充字符串。例如,假设您的分隔符是分号(因为您的字符串中有逗号),请按照以下方式填充字符串的左侧和右侧:

";Smith, John;Doe, Jane;"

还需填充搜索值,例如,如果您要查找 Smith,则该值会变为:

";Smith;"

.toLowerCase().indexOf()会返回-1(未找到)。但";Smith, John;"会返回0。


那也会找到“Smith”,例如。 - gsnedders
@gsnedders - 是的,它会。如果“Smith”是一个问题,可以对搜索字符串进行填充,使其成为精确匹配搜索。 - Chris Gessler
如果我理解得没错的话,这并没有真正回答问题。listFind() 这样的调用不仅仅是在字符串中查找项目(这个解决方案确实做到了),它还返回列表中的哪个位置(好吧 Peter,“带有分隔符的字符串,其中包含使这些分隔符具有特殊含义的函数,有点像人类会考虑列表一样,因此简称为'列表'”;-)。例如:如果您使用它来查找“Doe, Jane”,它将返回17(它在字符串中的位置),而不是2(它在“列表”中的位置)。 - Adam Cameron

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接