In cypress I have
Book
:This is the book of
English
how to test that 'Book:This is book of English' is in order ?
I not having single row I have multiple rows like this
cy.get('span').then((Val)=>{ const text=val.text().trim(':').toString(); });
The answer from #AsadMusharaf needs an extra step:
cy.get('span')
.then($span => {
return $span.text() // extract test
.split(': ') // split it at ": "
})
.should('deep.equal', ['Book', 'English']) // compare to ordered array
You have bold <b> elements, will need to add b in the selector
cy.get('span b')
.invoke('text')
.should('eq', 'BookEnglish')
cy.get('span').then(span => {
const words = span.split(':');
const firstword = words[0]
const secondword = words[1]
cy.log(firstword, secondword);
Try this. Here we are splitting the pair of words by ":" and storing them in array vairabled and calling that variables. Array [0] will have the text "Book" and array [1] will have the text "English"
you could just see if the whole string matches with contains after or as part of get
cy.get('span').contains('Book: English').should('exist')
// or
cy.get('span:contains("Book: English")').should('exist')
Related
I want extract from a table all rows where in a column (string) there is at least one word that starts with a specified character.
Example:
Row 1: 'this is the first row'
Row 2: 'this is th second row'
Row 3: 'this is the third row'
If the specified character is T -> I would extract all 3 rows
If the specified character is S -> I would extract only the second column
...
Please help me
Assuming you mean "space delimited sequence of characters, or begin to space or space to end" by "word", then you can split on the delimiter and test them for matches:
var src = new[] {
"this is the first row",
"this is th second row",
"this is the third row"
};
var findChar = 'S';
var lowerFindChar = findChar.ToLower();
var matches = src.Where(s => s.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries).Any(w => w.ToLower()[0] == lowerFindChar));
The LINQ Enumerable.Any method tests a sequence to see if any element matches, so you can split each string into a sequence of words and see if any word begins with the desired letter, compensating for case.
Try this:
rows.Where(r => Regex.IsMatch(r, " [Tt]"))
You can replace the Tt with Ss (both assuming you want either upper case or lower case).
The problem of course is, what is a "word"?
Is the character sequence 'word' in the sentence above a word according to your definition? It doesn't start with a space, not even a white-space.
A definition of a word could be:
Define wordCharacter: something like A-Z, a-z.
Define word:
- the non-empty sequence of wordCharacters at the beginning of a string followed by a non-wordcharacter
- or the non-empty sequence of wordCharacters at the end of a string preceded by a non-wordcharacter
- any non-empty sequence of wordCharacters in the string preceded and followed by a non-wordcharacter
Define start of word: the first character of a word.
String: "Some strange characters: 'A', 9, äll, B9 C$ X?
- Words: Some, strange characters, A
- Not Words: 9, äll, B9, C$ X?
So you first have to specify precisely what you mean by word, then you can define functions.
I'll write it as an extension method of IEnumerable<string>. Usage will look similar to LINQ. See Extension Methods Demystified
bool IsWordCharacter(char c) {... TODO: implement your definition of word character}
static IEnumerable<string> SplitIntoWords(this string text)
{
// TODO: exception if text null
if (text.Length == 0) return
int startIndex = 0;
while (startIndex != text.Length)
{ // not at end of string. Find the beginning of the next word:
while (startIndex < text.Length && !IsWordCharacter(text[startIndex]))
{
++startIndex;
}
// now startIndex points to the first character of the next word
// or to the end of the text
if (startIndex != text.Length)
{ // found the beginning of a word.
// the first character after the word is either the first non-word character,
// or the end of the string
int indexAfterWord = startWordIndex + 1;
while (indexAfterWord < text.Length && IsWordCharacter(text[indexAfterWord]))
{
++indexAfterWord;
}
// all characters from startIndex to indexAfterWord-1 are word characters
// so all characters between startIndexWord and indexAfterWord-1 are a word
int wordLength = indexAfterWord - startIndexWord;
yield return text.SubString(startIndexWord, wordLength);
}
}
}
Now that you've got a procedure to split any string into your definition of words, your query will be simple:
IEnumerabl<string> texts = ...
char specifiedChar = 'T';
// keep only those texts that have at least one word that starts with specifiedChar:
var textsWithWordThatStartsWithSpecifiedChar = texts
// split the text into words
// keep only the words that start with specifiedChar
// if there is such a word: keep the text
.Where(text => text.SplitIntoWords()
.Where(word => word.Length > 0 && word[0] == specifiedChar)
.Any());
var yourChar = "s";
var texts = new List<string> {
"this is the first row",
"this is th second row",
"this is the third row"
};
var result = texts.Where(p => p.StartsWith(yourChar) || p.Contains(" " + yourChar));
EDITED:
Alternative way (I'm not sure it works in linq query)
var result = texts.Where(p => (" " + p).Contains(" " + yourChar));
you can use .ToLower() if you want Case-insensitive check.
I have a query to the Cognitive text keyphase API from Microsoft from '16 Excel Power Query - getting keywords from tweets. Works fine.
However, the JSON doc that's returned per query is converted by Power Query into a list of ~1-5 rows.
In the case of the pic, I want all responses returned to be in one cell/row, regardless of the number of items returned.
Here is my full M query (you need to put your own key in) if you're interested.
let
TweetCognitive = (TweetID as text, TweetText as text) =>
let
JsonRecords = Text.FromBinary(Json.FromValue([id=TweetID, text=TweetText])),
JsonRequest = "{""documents"": [" & JsonRecords & "]}",
JsonContent = Text.ToBinary(JsonRequest, TextEncoding.Ascii),
Response =
Web.Contents("https://westus.api.cognitive.microsoft.com/text/analytics/v2.0/keyPhrases?",
[
Headers = [#"Ocp-Apim-Subscription-Key"="yourkeyhere",
#"Content-Type"="application/json", Accept="application/json"],
Content=JsonContent
]),
JsonResponse = Json.Document(Response,1252)
in
JsonResponse
in
TweetCognitive
You can use List.Accumulate to turn a list of values into a single value. For example, this would combine the values in the list into a single text value with ". " separating each row's value:
List.Accumulate(JsonResponse, "", (state, current) => state & current & ". ")
This would generate "monday frank love happiness today. nice good kind. tomorrow. " in your example. If you want to get rid of the trailing space, you can surround the List.Accumulate expression with Text.Trim.
The basic function to concatenate elements in a list is Text.Combine. For instance:
Text.Combine(JsonResponse, " ")
This avoids the extra delimeter at the end you get with List.Accumulate. Note also List.Combine is for creating a longer combined list from shorter lists, and the similar naming there may cause confusion.
I am new using java. I wanted to ask, if I have a text file containing different words per line and I want to read that file as a string in order to detect if there are certain words that are written in all caps (abbreviations). The exception being that if the word starts with "#" or and "#" it will ignore counting it. For example I have:
OMG terry is cute #HAWT SMH
The result will be:
Abbreviations = 2.
or
terry likes TGIF parties #ANDERSON
The result will be:
Abbreviations = 1.
Please help
Try to use the .split(String T) method, and the .contains(char C) methods .....
I think they will help you a lot ....
Function split:
http://www.tutorialspoint.com/java/java_string_split.htm
Function contains:
http://www.tutorialspoint.com/java/lang/string_contains.htm
String str1 = "OMG terry is cute #HAWT SMH";
String str2 = "terry likes TGIF parties #ANDERSON";
Pattern p = Pattern.compile("(?>\\s)([A-Z]+)(?=\\s)");
Matcher matcher = p.matcher(" "+str1+" ");//pay attention! adding spaces
// before and after to catch potentials in
// beginning/end of the sentence
int i=0;
while (matcher.find()) {
i++; //count how many matches were found
}
System.out.println("matches: "+i); // prints 2
matcher = p.matcher(" "+str2+" ");
i=0;
while (matcher.find()) {
i++;
}
System.out.println("matches: "+i); // prints 1
OUTPUT:
matches: 2
matches: 1
Here is a bazooka for your spider problem.
(mystring+" ").split("(?<!#|#)[A-Z]{2,}").length-1;
Pad the string with a space (because .split removes trailing empty strings).
Split on the pattern "behind this is neither # nor #, and this is two or more capital letters". This returns an array of substrings of the that are not part of abbreviations.
Take the length of the array and subtract 1.
Example:
mystring = "OMG terry is cute #HAWT SMH";
String[] arr = (mystring+" ").split("(?<!#|#)[A-Z]{2,}").length-1;
//arr is now {"", " terry is cute #HAWT ", " "}, three strings
return arr.length-1; //returns 2
I am trying to check an array of strings for containing one or more matching strings.
Currently I am doing this by using if statements - not nice, but it works - However now I am looking for a more Ruby-like way to do this.
row[:datapoints].each do |data|
if data[:direction].include? "Beusselstr"
data[:image] = "category-1"
end
if data[:direction].include? "Ostkreuz"
data[:image] = "category-1"
end
if data[:direction].include? "Westend"
data[:image] = "category-2"
end
if data[:direction].include? "1)S Gr"
data[:image] = "category-3"
end
end
Instead of this I'd like to store the matching strings in an array. To make it a bit more complicated I actually have different categories of matching terms with their own result actions (see category specific assignment of the data[:image] value).
category_1_keywords = ["Beusselstr","Ostkreuz"]
category_2_keywords = ["nefeld Bhf","Greifswalder","Westend"]
category_3_keywords = ["1)S Gr"]
imagecategories = {:category_1 => category_1_keywords,:category_2 => category_2_keywords,:category_3 => category_3_keywords}
How would filtering the array (row[:datapoints]) using such a matching array (imagecategories) look like?
You would probably want to use the array intersection operator & and check if it's empty.
if (data[:direction] & category_1_keywords).any?
data[:image] = "category-1"
end
4 if's in a row though start looking like time for an iterator:
keywords = {
'category_1' => ["Beusselstr","Ostkreuz"],
'category_2' => ["nefeld Bhf","Greifswalder","Westend"],
'category_3' => ["1)S Gr"]
}
data[:image] = keywords.find{|k,v| (data[:direction] & v).any?}[0]
Assuming that data[:direction] is a string, you can find the category with:
data[:image], _ = imagecategories.find { |category, keywords|
keywords.any? { |keyword|
data[:direction].include?(keyword)
}
}
In plain text: find the first category-keywords pair (imagecategories.find) having any keyword (keywords.any?) that the data[:direction] string contains.
I have a large file in a ruby variable, it follows a common pattern like so:
// ...
// comment
$myuser['bla'] = 'bla';
// comment
$myuser['bla2'] = 'bla2';
// ...
I am trying to given a 'key' replace the 'value'
This replaces the entire string how do I fix it? Another method I thought is to do it in two steps, step one would be to find the value within the quotes then to perform a string replace, what's best?
def keyvalr(content, key, value)
return content.gsub(/\$bla\[\'#{key}\'\]\s+\=\s+\'(.*)\'/) {|m| value }
end
The .* is greedy and consumes as much as possible (everything until the very last '). Make that . a [^'] then it is impossible for it to go past the first closing '.
/(\$bla\[\'#{key}\'\]\s+\=\s+\')[^']*(\')/
I also added parentheses to capture everything except for the value, which is to be replaced. The first set of parens will correspond to \1 and the second to \2. So that you replace the match of this with:
"\1yournewvaluehere\2"
I'd use something like:
text = %q{
// ...
// comment
$myuser['bla'] = 'bla';
// comment
$myuser['bla2'] = 'bla2';
// ...
}
from_to = {
'bla' => 'foo',
'bla2' => 'bar'
}
puts text.gsub(/\['([^']+)'\] = '([^']+)'/) { |t|
key, val = t.scan(/'([^']+)'/).flatten
"['%s'] = '%s'" % [ key, from_to[key] ]
}
Which outputs:
// ...
// comment
$myuser['bla'] = 'foo';
// comment
$myuser['bla2'] = 'bar';
// ...
This is how it works:
If I do:
puts text.gsub(/\['([^']+)'\] = '([^']+)'/) { |t|
puts t
}
I see:
['bla'] = 'bla'
['bla2'] = 'bla2'
Then I tried:
"['bla'] = 'bla'".scan(/'([^']+)'/).flatten
=> ["bla", "bla"]
That gave me a key, "value" pair, so I could use a hash to look-up the replacement value.
Sticking it inside a gsub block meant whatever matched got replaced by my return value for the block, so I created a string to replace the "hit" and let gsub do its "thang".
I'm not a big believer in using long regex. I've had to maintain too much code that tried to use complex patterns, and got something wrong, and failed to accomplish what was intended 100% of the time. They're very powerful, but maintenance of code is a lot harder/worse than developing it, so I try to keep patterns I write in spoon-size pieces, having mercy on those who follow me in maintaining the code.