英文:
Alternative to .replace() replacer function needed for multiple matches in a string
问题
.matchAll()
is a suitable alternative to .replace()
in this case for extracting matched substrings, and it can simplify your code. However, there's a difference in the output format between the two examples you provided. The first example extracts and pushes substrings and arrays into the results
array, while the second example directly extracts and returns an array of matched substrings using .matchAll()
.
If you want the output to match the format of the first example, where substrings and arrays are pushed into an array, you would need to modify the second example accordingly. Here's how you can achieve that:
const scan = (str, pattern) => {
return [...str.matchAll(pattern)].map((match) => {
const results = Array.prototype.slice.call(match, 1, -2);
return results.length === 1 ? results[0] : results;
});
}
With this modification, the output will be structured similarly to the first example.
英文:
I'm working on a project that does some string parsing (for a song lyrics format) and I ran across a usage of the .replace()
method that feels a bit hacky to me... but it does work.
This is how it currently works right now, and it logs out the expected result.
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
const scan = (str, pattern) => {
const results = [];
str.replace(pattern, function() {
results.push(Array.prototype.slice.call(arguments, 1, -2));
});
return _.flatten(results)
}
console.log("Lyrics", scan(
"I don't see! a bad, moon a-rising. (a-rising)",
/(\[[\w#b/]+])?([\w\s',.!()_\-"]*)/gi
));
console.log("Chords", scan(
"[D] [D/F#] [C] [A7]",
/\[([\w#b+/]+)]?/gi
));
console.log("Measures", scan(
`
# Instrumental
| [A] [B] | [C] | [D] [E] [F] [G] |
`,
/([[\w#b/\]+\]\s]+)[|]*/gi
));
<!-- language: lang-html -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js" integrity="sha512-WFN04846sdKMIP5LKNphMaWzU7YpMyCU245etK3g/2ARYbPK9Ub18eG+ljU96qKRCWh+quCY7yefSmlkQw1ANQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<!-- end snippet -->
The usage of .replace()
feels wrong since it's not actually doing any replacing but relying on the looping behavior to push items into an array. That returns an array with a single item, of an array of strings. Lodash is then used to flatten it out into a single string array.
I feel like this could be improved to use .matchAll()
instead, but I haven't been able to get it quite right just yet. Here's what I have so far, which works but the output is wrong since it's not identical to the above example.
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
const scan = (str, pattern) => {
return [...str.matchAll(pattern)].map(r=>{
return r[1]
});
}
console.log("Lyrics", scan(
"I don't see! a bad, moon a-rising. (a-rising)",
/(\[[\w#b/]+])?([\w\s',.!()_\-"]*)/gi
));
console.log("Chords", scan(
"[D] [D/F#] [C] [A7]",
/\[([\w#b+/]+)]?/gi
));
console.log("Measures", scan(
`
# Instrumental
| [A] [B] | [C] | [D] [E] [F] [G] |
`,
/([[\w#b/\]+\]\s]+)[|]*/gi
));
<!-- end snippet -->
Is .matchAll()
the correct alternative to .replace()
in this case? Is there a better way to get the desired output instead of what I am currently doing? I know I'm currently not calling the .slice()
method that the first example has yet because I'm not entirely sure I understand what this is trying to accomplish here since this code was not originally written by me.
答案1
得分: 0
You can use flatMap
and slice
.
const pattern = /(\[[\w#b/]+])?([\w\s',.!()_\-"]*)/gi;
const str = "I don't see! a bad, moon a-rising. (a-rising)"
const results = [...str.matchAll(pattern)].flatMap(m => m.slice(1));
console.log('results', results)
(Note: I've kept the code portion in its original format, including HTML entities like "
and >
. If you want those entities translated, please let me know.)
英文:
You can use flatMap
and slice
.
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
const pattern = /(\[[\w#b/]+])?([\w\s',.!()_\-"]*)/gi;
const str = "I don't see! a bad, moon a-rising. (a-rising)";
const results = [...str.matchAll(pattern)].flatMap(m => m.slice(1));
console.log('results', results)
<!-- end snippet -->
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论