Is there a way to extract multiple WebElements from within a WebElement? For instance I have the following:
String filterRowXpath = "(//div[#id=\"tabItemFilters\"]//div[#id=\"RowExpGridWidgetGridPanel\"]//div[#class=\"x-grid3-body\"]//tbody)";
List<WebElement> filterRows = driver.findElements(By.xpath(filterRowXpath));
I end up with a WebElement that contains 5 elements itself, is there a way for me to reference elements 2 and 3 for instance?
Here's what I came up with:
String ipFromValueXpath;
String ipToValueXpath;
for(int i=1; i<=filterRows.size(); ++i) {
ipFromValueXpath = "(((//div[#id=\"tabItemFilters\"]//div[#id=\"RowExpGridWidgetGridPanel\"]//div[#class=\"x-grid3-body\"]//tbody)[" + i + "])//td)[2]";
ipToValueXpath = "(((//div[#id=\"tabItemFilters\"]//div[#id=\"RowExpGridWidgetGridPanel\"]//div[#class=\"x-grid3-body\"]//tbody)[" + i + "])//td)[3]";
WebElement e1 = driver.findElement(By.xpath(ipFromValueXpath));
String ipFromValue = e1.getText();
WebElement e2 = driver.findElement(By.xpath(ipToValueXpath));
String ipToValue = e2.getText();
if(ipFromValue.equals(ipFrom) && ipToValue.equals(ipTo)) {
e1.click();
element = driver.findElement(By.xpath(deleteFilterButtonXpath));
element.click();
Thread.sleep(500);
AdminFunctions.apply();
return;
}
}
I had to get the Xpath for each element then iterate through each row to find a match. I don't think it's the most efficient way to do it though.
If you have something like :
<tbody>
<webelement>1<webelement/>
<webelement>2<webelement/>
<webelement>3<webelement/>
</tbody>
And you want 2 or 3, you can add [2] or [3] which is equivalent to [position()=2] or [position()=3].
So for your XPath it would be ..//tbody[position()=2 or position()=3] if you're looking for either of those positions. Note that you cannot use shorthand as in the previous statement if you are searching for multiple positions.
UPDATE:
filterRowXpath= "(((//div[#id=\"tabItemFilters\"]//div[#id=\"RowExpGridWidgetGridPanel\"]//div[#class=\"x-grid3-body\"]//tbody)[" + i + "])//td)[position()=2 or position()=3]
This will give you two node results back, instead of executing separate xpaths for each one.
List<WebElement> filterRows = driver.findElements(By.xpath(filterRowXpath));
Then apply your condition to the WebElements. You were almost there in the snippet posted in your original question.
Related
Hi guys I am really stuck in this one situation :S I have a local .txtfile with a random sentence and my program is meant to :
I am finding it difficult to execute the third question. My code is ..
JavaScript
lengths.forEach((leng) => {
counter[leng] = counter[leng] || 0;
counter[leng]++;
});
$("#display_File_most").text(counter);
}
}
r.readAsText(f);
}
});
</script>
I have used this question for help but no luck - Using Javascript to find most common words in string?
I believe I have to store the sentence in an array and loop through it, uncertain if that is the correct step or if there is quicker way of finding the solution so I ask you guys.
Thanks for your time & I hope my question made sense :)
If you think of your solution as separated well done tasks, it would be really simple to find it. Here you have them together:
Convert the words into an array. Your guts were right about this :)
var source = "Hello world & good morning. The date is 18/09/2018";
var words = source.split(' ');
The next step is to find out the length of each word
var lengths = words.map(function(word) {
return word.length;
});
Finally the most complicated part is to get the number of occurrences for each length. One idea is to use an object to use key/value where key is the length and value is its count (source: https://stackoverflow.com/a/10541220/1505348)
Now you will see under the counter object have each word length with its repetition number on the source string.
var source = "Hello world & good morning. The date is 18/09/2018";
var words = source.split(' ');
var lengths = words.map(function(word) {
return word.length;
});
var counter = {};
lengths.forEach((leng) => {
counter[leng] = counter[leng] || 0;
counter[leng]++;
});
console.log(counter);
3.Produce a list of number of words of each length in sentence (not done).
Based on the question would this not be the solution?
var words = str.split(" ");
var count = {};
for (var i = 0; i<words.length; i++){
count[words[i].length] = (count [words[i].length] || 0) + 1
}
map < string , int > M;
M["Top"] = 1;
M["Coder"] = 2;
M["SRM"] = 10;
int x = M["Top"] + M["Coder"];
if(M.find("SRM") != M.end()) {
M.erase(M.find("SRM")); // or even M.erase("SRM")
}
If no element is found in the M, find() returns M.end(). M.end() points to the element following the last element of the container, it is a
boundary iterator (no data is at this position).
See:
http://en.cppreference.com/w/cpp/container/map/find
http://en.cppreference.com/w/cpp/container/map/end
The code works fine, when the string "SRM" is found in the map, it will be erased from it. Because when method find() does not finds the value it returns an iterator pointing to the end of container.
Maybe you could reformulate question, to be more precise what you want to achieve.
What Kind of algorithms + data structures that would help me to do that?
Having a file contains like 10000~ lines loaded in memory in a ordered set. With a given search string I want to be able to get all the lines that have words prefixed with words found in search string. Well let me give an example to clarify this:
Lines:
"A brow Fox flies."
"Boxes are full of food."
"Cats runs slow"
"Dogs hates eagles"
"Dolphins have eyes and teath"
Cases 1:
search string = "fl b a"
"A brow Fox flies."
Explanation: search string have three words "fl", "b", and "a" and
the only string that have some words that are prefixed with words
from the search string is line 1.
Case 2:
search string "e do ha"
"Dogs hates eagles", "Dolphins have eyes and teath"
Solution
(fast enough for me it took about 30ms~(including sorting the final result) on my pc on a set of 10k lines 3 words each line)
I used a trie suggested in answer.
And some other hacky methods to be able to filter out duplicate and false positive results (mainly used hash sets for this).
I think what you're probably wanting is a trie. Construct one for the set of all words in your document, and have each leaf point to a hashset containing the indices of the lines in which the key of the leaf appears.
To execute a search, you'd use each fragment of the search string to navigate to a node in the tree and take the union over the hashsets of all leaves in that node's subtree. Then you'd take the intersection of those unions over the set of fragments to get the list of lines satisfying the search string.
Here is my 2 cents:
class DicVal
{
public int OriginalValue;
public int CurrentValue;
public int LineNumber;
}
private static void Main()
{
var a = "A brow Fox flies.\r\n" +
"Boxes are full of food.\r\n" +
"Cats runs slow\r\n" +
"Dogs hates eagles\r\n" +
"A brow Fox flies. AA AB AC\r\n" +
"Dolphins have eyes and teath";
var lines = a.Split(new[] {Environment.NewLine}, StringSplitOptions.RemoveEmptyEntries);
var dic = new Dictionary<string, DicVal>
{
{"fl", new DicVal { OriginalValue = 1, LineNumber = -1}},
{"b", new DicVal { OriginalValue = 1, LineNumber = -1}},
{"a", new DicVal { OriginalValue = 4, LineNumber = -1}}
};
var globalCount = dic.Sum(x => x.Value.OriginalValue);
var lineNumber = 0;
foreach(var line in lines)
{
var words = line.Split(' ');
var currentCount = globalCount;
foreach (var word in words.Select(x => x.ToLower()))
{
for (var i = 1; i <= word.Length; i++)
{
var substr = word.Substring(0, i);
if (dic.ContainsKey(substr))
{
if (dic[substr].LineNumber != lineNumber)
{
dic[substr].CurrentValue = dic[substr].OriginalValue;
dic[substr].LineNumber = lineNumber;
}
if (dic[substr].CurrentValue > 0)
{
currentCount--;
dic[substr].CurrentValue--;
}
}
}
}
if(currentCount == 0)
Console.WriteLine(line);
lineNumber++;
}
}
Not going to explain much, as code is the best documentation :P.
Output: A brow Fox flies. AA AB AC
Assuming you implement everything efficiently, the running time will be as good as possible, since you need to read every word at least ONCE.
Further optimization can be done and apply threading. You can view into PARALLEL AGGREGATION concept, as this problem can be parallelized easily.
Here's a fairly simple implementation that should be appropriate for your use case. The idea is that you can store all combinations of short prefixes for each line (and for each query) since you only have 10,000 lines and assuming each line doesn't contain too many words. Now look up each hash generated for the query string. For each hash match, we then check for an exact match. For my example code I consider only prefixes of length 1, however you could repeat this approach for prefixes of length 2 & 3 provided the prefixes in your query have those lengths too.
__author__ = 'www.google.com/+robertking'
from itertools import combinations
from collections import defaultdict
lines = [
"A brow Fox flies.",
"Boxes are full of food.",
"Cats runs slow",
"Dogs hates eagles",
"Dolphins have eyes and teath"
]
lines = [line.lower() for line in lines]
def short_prefixes(line):
for word in line.split():
yield word[:1]
def get_hashes(line):
starts = list(short_prefixes(line))
for prefixes_in_hash in range(1, min(4, len(starts))):
for hash_group in combinations(starts, r=prefixes_in_hash):
yield tuple(sorted(hash_group))
def get_hash_map():
possible_matches = defaultdict(list)
for line_pos, line in enumerate(lines):
for hash in get_hashes(line):
possible_matches[hash].append(line_pos)
return possible_matches
possible_matches = get_hash_map()
def ok(line, q):
return all(line.startswith(prefix) or ((" " + prefix) in line) for prefix in q)
def query(search_string):
search_string = search_string.lower()
q = search_string.split()
hashes = set(get_hashes(search_string))
possible_lines = set()
for hash in hashes:
for line_pos in possible_matches[hash]:
possible_lines.add(line_pos)
for line_pos in possible_lines:
if ok(lines[line_pos], q):
yield lines[line_pos]
print(list(query("fl b a")))
#['a brow fox flies.']
I have a class that contains a ints, string and pointers to other classes. I'm trying to extract the strings and perform a substring operation on them before I select.Distinct. My LINQ code looks right
List<string> crops = (from m in cropTypes
let cw = m.CropName
let kw = cw.Substring(0, cw.LastIndexOf(")") + 1)
select(kw).Distinct()).ToList();
I have also tried
var crop = …
List<string> crops = crop.ToList();
When I attempt to compile, I'm getting
Cannot implicitly convert type
System.Collections.Generic.List<System.Collections.Generic.IEnumerable<char>> to System.Collections.Generic.List<System.Collections.Generic.IEnumerable<string>>
on the ToList() line.
m.CropName is definitely a string
Why does the compiler think that I'm using a char list rather than a string list and how do I fix this.
Nothing like a simple problem to stump you at the start of a day!
try
List<string> crops = (from m in cropTypes
let cw = m.CropName
let kw = cw.Substring(0, cw.LastIndexOf(")") + 1)
select kw).Distinct().ToList();
If you call Distinct on a string, you're actually enumerating the string's characters.
Source : Microsoft Interview Question
We are given a File containing words.We need to determine all the Anagrams Present in it .
Can someone suggest most optimal algorithm to do this.
Only way i know is
Sorting all the words,then checking .
It would be good to know more about data before suggesting an algorithm, but lets just assume that the words are in English in the single case.
Lets assign each letter a prime number from 2 to 101. For each word we can count it's "anagram number" by multiplying its letter corresponding numbers.
Lets declare a dictionary of {number, list} pairs. And one list to collect resulting anagrams into.
Then we can collect anagrams in two steps: simply traverse through the file and put each word to a dictionary's list according to its "anagram number"; traverce the map and for every pairs list with length more then 1 store it's contents in a single big anagram list.
UPDATE:
import operator
words = ["thore", "ganamar", "notanagram", "anagram", "other"]
letter_code = {'a':2, 'b':3, 'c':5, 'd':7, 'e':11, 'f':13, 'g':17, 'h':19, 'i':23, 'j':29, 'k':31, 'l':37, 'm':41, 'n':43,
'o':47, 'p':53, 'q':59, 'r':61, 's':67, 't':71, 'u':73, 'v':79, 'w':83, 'x':89, 'y':97, 'z':101}
def evaluate(word):
return reduce( operator.mul, [letter_code[letter] for letter in word] )
anagram_map = {}
anagram_list = []
for word in words:
anagram_number = evaluate(word)
if anagram_number in anagram_map:
anagram_map[ anagram_number ] += [word]
else:
anagram_map[ anagram_number ] = [word]
if len(anagram_map[ anagram_number ]) == 2:
anagram_list += anagram_map[ anagram_number ]
elif len(anagram_map[ anagram_number ]) > 2:
anagram_list += [ word ]
print anagram_list
Of course the implementation can be optimized further. For instance, you don't really need a map of anagrams, just a counters would do fine. But I guess the code illustrates the idea best as it is.
You can use "Tries".A trie (derived from retrieval) is a multi way search tree. Tries use pattern matching algorithms. It's basic use is to create spell check programs, but I think it can help your case..
Have a look at this link http://ww0.java4.datastructures.net/handouts/Tries.pdf
I just did this one not to long ago, in a different way.
split the file content into an array of words
create a HashMap that maps a key string to a linked list of strings
for each word in the array, sort the letters in the word and use that as the key to a linked list of anagrams
public static void allAnagrams2(String s) {
String[] input = s.toLowerCase().replaceAll("[^a-z^\s]", "").split("\s");
HashMap> hm = new HashMap>();
for (int i = 0; i < input.length; i++) {
String current = input[i];
char[] chars = current.toCharArray();
Arrays.sort(chars);
String key = new String(chars);
LinkedList<String> ll = hm.containsKey(key) ? hm.get(key) : new LinkedList<String>();
ll.add(current);
if (!hm.containsKey(key))
hm.put(key, ll);
}
}
Slightly different approach from the one above. Returning a Hashmap of anagrams instead.
Public static Hashmap<String> anagrams(String [] list){
Hashmap<String, String> hm = new Hashmap<String, String>();
Hashmap<String> anagrams = new Hashmap<String>();
for (int i=0;i<list.length;i++){
char[] chars = list[i].toCharArray();
Arrays.sort(chars);
String k = chars.toString();
if(hm.containsKey(k)){
anagrams.put(k);
anagrams.put(hm.get(k));
}else{
hm.put(k, list[i]);
}
}
}