在字符串中的 Y 索引处查找 X 字符并使用此信息过滤数组

Posted

技术标签:

【中文标题】在字符串中的 Y 索引处查找 X 字符并使用此信息过滤数组【英文标题】:Find X character at Y index in string and filter an array using this information 【发布时间】:2021-06-28 21:45:04 【问题描述】:

我有一个字符串和一个字符串数组。字符串示例如下:

let example1 = "_a_t_";
let example2 = "N_l_:t___";
let example3 = "B__z_l";

我们可以看到,字符串有 Z 个字符长,并且有随机数量的字符不是 _。字符串永远不会只有 _,也不会没有下划线。

let array = ["Walts", "Grate", "Ralts", "Names"];

如果我们使用example1字符串和上面的数组,我想过滤数组,结果变成:

let newArray = ["Walts", "Ralts"];

基本上,我想使用已知字符及其位置来过滤数组。目前我已经找到了如何找到第一个字符并使用它来过滤数组。这样做是这样的:

let example1 = "_a_t_";
let array = ["Walts", "Grate", "Ralts", "Names"];

let charIndex = example1.match("[a-zA-Z]").index;
/*Currently using the RegEx [a-zA-Z], but this should be changed to include all characters 
besides underscores but I don't know what to put in between the square brackets*/
let firstChar = example1.charAt(charIndex);

let filteredArray = array.filter(function (element) 
  return element.charAt(charIndex) === firstChar;
);

console.log(filteredArray); //this returns ["Walts", "Ralts", "Names"]

我在这里卡住了。如果字符串中有多个显示的字符,我不知道该怎么做。经过一番思考,对我来说合乎逻辑的事情是以某种方式计算所有不是下划线的字符,然后使用它,进行循环。循环将找到每个字符及其索引,然后过滤数组。当数组被完全过滤时,循环将结束。使用上面的数组和example1 字符串,希望得到["Walts", "Ralts"]

我认为问题得到了彻底的解释,最终目标也很明确。这是我第一次在 Stack Overflow 上发帖,非常激动。

【问题讨论】:

对于除下划线以外的所有字符,使用/[^_]/ 不过我会使用正则表达式而不是字符串。 【参考方案1】:

另一种选择是创建一个正则表达式并将所有单词与| 作为分隔符加入非捕获组中,并将_ 替换为\S 以匹配非空格char 不匹配空格

图案看起来像:

^(?:\Sa\St\S|N\Sl\S:t\S\S\S|B\S\Sz\Sl)$

模式匹配:

^ 字符串开始 (?:非捕获组 \Sa\St\S 第一种选择,其中\S 匹配非空白字符 |或者 N\Sl\S:t\S\S\S 第二种选择 |或者 B\S\Sz\Sl 第三种选择 )关闭非捕获组 $字符串结束

例如

let example1 = "_a_t_";
let example2 = "N_l_:t___";
let example3 = "B__z_l";
let array = ["Walts", "Grate", "Ralts", "Names"];
const strings = [example1, example2, example3];
const regex = new RegExp(`^(?:$strings.join("|").replace(/_/g, "\\S"))$`);
console.log(array.filter(s => regex.test(s)));

如果要匹配空格,可以使用. 代替\S

注意,在RegExp() 构造函数中,您必须对反斜杠进行双重转义。如果任何字符串包含正则表达式的特殊字符,您必须 escape 这些字符。

另一个例子:

const escapeRegExp = s => s.replace(/[-\/\\^$*+?.()|[\]]/g, '\\$&');
let example1 = "_a_t_";
let example2 = "N_l_:t___";
let example3 = "B__z_l";
let example4 = "T__()"
let array = ["Walts", "Grate", "Ralts", "Names", "Tab()"];
const strings = [example1, example2, example3, example4].map(s => escapeRegExp(s));
const regex = new RegExp(`^(?:$strings.join("|").replace(/_/g, "."))$`);
console.log(array.filter(s => regex.test(s)));

【讨论】:

感谢您的回答!它在代码 sn-p 中工作,当放入连接到 html 文件的 js 文件时。但是,我对您的解决方案(以及 ray hatfield 的解决方案)有疑问。我在一个节点项目中运行了这个 sn-p,得到了错误TypeError: strings.join(...).replaceAll is not a function。我该如何解决这个问题? @OscaHar 我已将其更新为使用替换。 replaceAll 相对较新,isn't supported 适用于所有环境。 Node 在 15.0 中添加了支持。如果您希望它在任何地方都可以工作,您可能需要使用正则表达式进行替换调用而不是 replaceAll。 非常感谢你们俩。它按照我想要的方式工作,同时仍然很高效,而且线条不多。非常感谢!【参考方案2】:

我认为如果您从每个模式创建一个regular expression 并仅针对整个模式测试每个字符串,这可能会更容易。这是概念实施的快速证明。

它只是在创建表达式时将_替换为.,因此下划线将匹配任何字符,然后根据字符串是否匹配过滤数组。

例如,字符串 "_a_t_" 变为匹配 Walts 和 Ralts 但不匹配 Grate 或 Names 的正则表达式 /^.a.t.$/gi

正则表达式模式/^.a.t.$/gi 松散地转换为:

^ 字符串开头 . 后跟任意字符 a 后跟文字“a” . 后跟任意字符 t 后跟文字“t” . 后跟任意字符 $ 字符串结束。

const example1 = "_a_t_";
const example2 = "N_l_:t___";
const example3 = "B__z_l";
const array = ["Walts", "Grate", "Ralts", "Names"];

// turn the string patterns into regular expressions
const regexes = [example1, example2, example3].map(pattern => 
  return new RegExp(`^$pattern.replaceAll('_', '.')$`, 'i');
);

// filter out names that don't match any of the expressions
const result = array.filter(name => regexes.some(r => r.test(name)));
  
console.log(result);

编辑:更新以简化示例实现。

【讨论】:

The forth bird's solution 是相同的核心思想,但通过将表达式连接成一个模式,他的效率更高。您可以通过将我的 map 迭代替换为 join('|') 并创建单个 RegEx 来调整我的方法。 确认。 “第四”。哎呀。

以上是关于在字符串中的 Y 索引处查找 X 字符并使用此信息过滤数组的主要内容,如果未能解决你的问题,请参考以下文章

880. 索引处的解码字符串

Leetcode(884)-索引处的解码字符串

在数字中的特定数字处查找数字[关闭]

算法:按字典顺序在给定索引处查找给定字符串的字谜

文本区域中的光标位置(字符索引,不是 x/y 坐标)

为啥我不能将此信息从一个反应组件推送到另一个?