replace some parts for cloze deletion test - javascript

For example, I have this text: This is a good reason to stop. (word counts is always greater than 5)
words = ['This', 'is', 'a', 'good', 'reason', 'to', 'stop']
flashcards_count = ciel(len(word) / 3)
The result I'd like to have:
[
'This __ a good ______ to ____.'
'____ is a ____ reason __ stop.'
'This is _ good reason to stop.'
]
As you may notice I'm try to avoid putting blanks in sequence, except if it's the last flashcard.
So for this, I shuffled the words and chunked it into 3 to make each flashcard, but the result might be like this:
[
'This is a ____ ______ __ stop.'
'____ __ _ good reason to stop.'
'This is a good reason to ____.'
]

You can use the random module to shuffle a list of strings, then join them with a space inbewteen :
import random
list = ['This', 'is', 'a', 'good', 'reason', 'to', 'make', 'stop']
random.shuffle(list)
print " ".join(list)
Take a look at Shuffling a list of objects if you want to shuffle non-strings aswel.

Related

Get multiple substrings between " or '

I am trying to figure out how to get substrings when the substrings are either located between a ' (single quote) or " (double quote)
Example:
Input: The "quick" brown "fox" 'jumps' over the 'lazy dog'
Output: ['quick', 'fox', 'jumps', 'lazy dog']
I have tried doing this with a regex but fell flat.
const string = "The "quick" brown "fox" 'jumps' over the 'lazy dog'"
const pattern = /(?:'([^']*)')|(?:"([^"]*)")/;
console.log(strippedText.match(pattern));
But it only returns the first single quoted or double quotes word.
Use the global flag, g, after the last / in the pattern, and change the function from match to matchAll. So: pattern = /(?:'([^']*)')|(?:"([^"]*)")/g;. This returns an array of arrays, so you'll need to do processing on that to get the normal array that you want.
const string = `The "quick" brown "fox" 'jumps' over the 'lazy dog'`; // Uses backticks since we use " and '
const pattern = /(?:'([^']*)')|(?:"([^"]*)")/g; // Pattern has the global flag "g" at the end so it allows multiple matches
const matches = [...string.matchAll(pattern)] // Convert RegExpStringIterator into array with the spread operator "..."
.map(([_, first, second]) => first ?? second); // Convert the array of arrays into something sensible.
console.log(matches);
Without mapping, matches would look like this:
[
[
"\"quick\"",
null,
"quick"
],
[
"\"fox\"",
null,
"fox"
],
[
"'jumps'",
"jumps",
null
],
[
"'lazy dog'",
"lazy dog",
null
]
]
So with this line:
.map(([_, first, second]) => first ?? second)
We destructure the inner array, discarding the 0th index (which is the whole match, including things inside a "do no match" group (?:), so it includes the quotes at the beginning and end), and extracting the 1st and 2nd indices. The first ?? second means that if first is not null or undefined, it returns first, otherwise it returns second.

How to split text by regex not in quotation marks

I am using text.split(' ') to split text by 'space'.
Example:
Hi my name is John
to
['Hi', 'my', 'name', 'is', 'John'];
I would like to ignore spaces in question mark.
Hi pls 'DO NOT SPLIT THIS'
to
['Hi', 'pls', 'DO NOT SPLIT THIS']
How can I do this?
Thank you for any help!
How about the following?
regex = /\s+(?=(?:[^\'"]*[\'"][^\'"]*[\'"])*[^\'"]*$)/g
"Hi pls 'DO NOT SPLIT THIS'".split(regex)
// [ 'Hi', 'pls', "'DO NOT SPLIT THIS'" ]

JavaScript - Regex split string to array allowing for apostrophes

I have some Express middleware which handles a string - a sentence entered by a user through a text field - and does some analysis on it. For this I need both the words and the punctuation broken into an array.
An example string is:
"It's familiar. Not much has really changed, which is surprising, but
it's nice to come back to where I was as a kid."
As part of the process I replace new lines with <br /> and split the string into an array
res.locals.storyArray =
res.locals.story.storyText.replace(/(?:\r\n|\r|\n)/g, ' <br/>' ).split(" ");
this works to a certain degree but when a sentence contains an apostrophe e.g. "It's familiar. things get thrown out of sync and I get an array like (note that there is detail I'm not showing here regarding how the word gets mapped to its grammar type) :
[ [ '"', 'quote' ],
['It', 'Personal pronoun' ], <--these items are the issue
[ '\'', 'quote' ], < --------these items are the issue
[ 's', 'Personal pronoun'], <------these items are the issue
[ 'familiar', 'Adjective' ],
[ '.', 'Sent-final punct' ],
[ 'Not', 'Adverb' ],
[ 'much', 'Adjective' ],
[ 'has', 'Verb, present' ],
[ 'really', 'Adverb' ],
[ 'changed', 'verb, past part' ],
[ ',', 'Comma' ],
[ 'which', 'Wh-determiner' ],
[ 'is', 'Verb, present' ]]
I'm actually surprised that the commas and full stops seem to be split correctly seeing I am only splitting on white space but I'm trying to get my array to be:
[ [ '"', 'quote' ],
[ 'It's, 'Personal pronoun' ],
[ 'familiar', 'Adjective' ],
[ '.', 'Sent-final punct' ],
.....
]
You could use String.raw to make sure the string remains correctly in-tact with included punctuation.
The only issue I had was in keeping the "." punctuation marks. For that I added a new replace function before splitting .replace(/\./g, " .") - this was done for all commas as well.
let strArray = myStr.replace(/\./g, " .")
.replace(/\,/g, " ,")
.replace(/\"/g, String.raw` " `)
.split(/\s/g)
.filter(_=>_);
let myStr = String.raw `"It's familiar. Not much has really changed, which is surprising, but
it's nice to come back to where I was as a kid."`;
let strArray = myStr.replace(/\./g, " .")
.replace(/\,/g, " ,")
.replace(/\"/g, String.raw` " `)
.split(/\s/g)
.filter(_=>_);
let HTML = myStr.replace(/(?:\r\n|\r|\n)/g, " <br/>");
console.log(myStr);
console.log(strArray);
EDIT: Added replace for comma separation as well.
I'm not sure what you expect to be done about the <br/> - it seems silly to insert them while trying to turn your string into an array. In the code I've separated the process. You now have a string that spits out with <br/> tags and another variable that contains the array.
If you have any supplemental information, if this doesn't solve your issue, I'd be happy to help

Determine if a string contains 3 words in order from each of 3 word arrays [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
How can I test a string to see if it contains a single word each, in order, from three arrays of words? I want true to be printed in the console when the test string message (see below) contains words, in order, from the three arrays. The first word in order should be any of the words in the first_word array. The second word should be any word in the second_word array, and the same for the third word from the third_word array. The words will always be separated by a single space, and no other separator character(s).
The words should be detected anywhere within the test string (i.e. there can be any contents prior to, or after the words). It should still print true if there is something before or after the elements from first_word, second_word, and third_word.
This is what I currently have:
var message = '';
var first_word = ['nice', 'cool', 'awesome'];
var second_word = ['red', 'blue', 'green'];
var third_word = ['apple', 'pear', 'mango'];
if (message.includes(first_word + ' ' + second_word + ' ' + third_word)) {
console.log(true);
}
Test cases that should occur:
message = 'nice blue mango' // true
message = 'red nice apple' // false (not in order)
message = 'red nice apple, nice green apple' // true (contains words in order somewhere in string)
message = 'nice red' // false (does not contain third word)
message = 'nice very blue mango' // false (there is a word in-between)
The third example is true because nice green apple are elements from the array in the right order.
Use a regular expression generated from your word arrays
In my opinion, the easy way to do this is to generate a regular expression (RegExp) from your word arrays. Then use that RegExp to test for the sequence of words that you desire.
//Create the RegExp
regExp = new RegExp([first_word, second_word, third_word].map(list => '(?:' + list.join('|') + ')').join(' '));
//Check the test cases
testCases.forEach(message => console.log(regExp.test(message)));
<!-- Setup from question -->
<script>
let testCases = [
'nice blue mango', // true
'red nice apple', // false (not in order)
'red nice apple, nice green apple', // true
'nice red', // false (does not contain third word)
'nice very blue mango', // false (there is a word in-between)
'lol nice blue mango', // true (additional, from OP's comment)
];
var first_word = ['nice', 'cool', 'awesome'];
var second_word = ['red', 'blue', 'green'];
var third_word = ['apple', 'pear', 'mango'];
</script>
What this does
Breaking this down, what this does is first create an array containing the arrays of words for which we are searching:
[first_word, second_word, third_word]
Results in:
[
["nice","cool","awesome"],
["red","blue","green"],
["apple","pear","mango"]
]
.map() is then called to map that array into an array of the regular expression text for each set of words. .join('|') is used to concatenate all of the words in a list into one string with the words separated by |.
[first_word, second_word, third_word].map(list => '(?:' + list.join('|') + ')')
Results in:
[
"(?:nice|cool|awesome)",
"(?:red|blue|green)",
"(?:apple|pear|mango)"
]
These are then .join(' ')ed into one string with spaces separating each list. This results in:
(?:nice|cool|awesome) (?:red|blue|green) (?:apple|pear|mango)
which is the string used to create the regular expression, using new RegExp(). The regular expression is then used to .test() each message string to see if the specified words are in the desired order.
Possibly slower than other, more complex solutions
While easy, using a RegExp may not be the highest performance method for obtaining the result. If you're testing huge numbers of strings, then you might want to look into improving performance by using an alternate method.
var message = 'lol nice red apple';
var first_word = ['nice', 'cool', 'awesome'];
var second_word = ['red', 'blue', 'green'];
var third_word = ['apple', 'pear', 'mango'];
var messages = message.trim().split(',');
var splitMessage = null;
var resultCount = 0;
var startFrom = 0;
messages.forEach(function(msg){
splitMessage = msg.trim().split(' ');
while(!first_word.includes(splitMessage[startFrom])){
startFrom++;
}
if(first_word.includes(splitMessage[startFrom]) && second_word.includes(splitMessage[startFrom + 1]) && third_word.includes(splitMessage[startFrom + 2])){
resultCount++;
}
})
console.log(resultCount === messages.length)

.split() on elements of a sentence string, advanced separator

I want to be able to split a sentence string into an array of individual word strings.
sentenceArr = 'I take the dog to the park'
sentenceArr.split(' ');
Desired result: ['I', 'take', 'the', 'dog', 'to', 'the', 'park']
This is easy if they are just split by spaces as above, but if there are commas or double spaces, or RegExes in the string it can come unstuck.
sentenceArr = 'I take,the dog to\nthe park'
sentenceArr.split(' ');
How can I modify the split() separator argument to account for these irregularities?
Ideally, I want to be able to split anywhere there isn't a letter.
split also takes a regex as argument :
sentenceArr = 'I take,the dog to\nthe park'
var r= sentenceArr.split(/\W+/);
console.log(r)

Categories

Resources