【问题标题】:Two loops for into stream两个循环进入流
【发布时间】:2021-08-10 13:47:14
【问题描述】:

我有一些带有两个 for 和 if 的 String 方法:

public String getCellValue(String stringFirst, int integerFirst) {
    List<WebElement> tableRows = driver.findElements(By.xpath("//table[@id='dt']/tbody/tr"));

    int index = 0;
    WebElement dataCell = null;

    for (WebElement row : tableRows) {
        index++;

        List<WebElement> tableCells = row.findElements(By.tagName("td"));

        for (WebElement cell : tableCells) {

            if (getTextFromElement(cell).equals(stringFirst)) {

                dataCell = driver.findElement(By.xpath(String.format("//table[@id='dt']/tbody/tr[%s]/td[%s]", index, integerFirst)));
            }
        }
    }

    return getTextFromElement(dataCell);
}

我仍然尝试将此实现更改为某个流。在这种情况下可能吗?我尝试了很多选项,但我在索引 (index++;) 和 tableCells By.tagname 中的过滤器方面遇到了问题。我认为不可能将完整的方法更改为流式传输,但我不知道。你能帮我实现一些吗?
非常感谢。

【问题讨论】:

    标签: java selenium for-loop java-stream


    【解决方案1】:

    了解给定数据:

    获取所有行:

    driver.findElements(By.xpath("//table[@id='dt']/tbody/tr"))
    
    

    获取给定行的列(单元格):

    row.findElements(By.tagName("td"))
    

    获取给定列(单元格)的文本:

    getTextFromElement(cell)
    

    如果行索引单元格上的文本匹配给定的字符串(stringFirst),则预期结果:

    driver.findElement(By.xpath(String.format("//table[@id='dt']/tbody/tr[%s]/td[%s]", index, integerFirst)))  
    

    从需求来看,似乎逻辑应该围绕索引。

    方法细分:

    首先,我们需要一个行列表。这和以前完全一样:

    List<WebElement> tableRows = driver.findElements(By.xpath("//table[@id='dt']/tbody/tr"));
    

    现在我们将创建一个包含所有索引的 IntStream。
    rangeClosed 意味着结束是包容的
    boxed() 用于将原始整数转换为整数

    IntStream.rangeClosed(1,tableRows.size()).boxed()
    
    1,
    2,
    3,
    ...
    

    为每个索引idx创建一个map,idx为key,row idx对应的column为value:

    .map(idx -> Map.of(idx, list.get(idx-1).findElements(By.tagName("td"))))
    
    {1=[cell11, cell12, cell13]},
    {2=[cell21, cell22, cell23]},
    ...
    

    合并所有地图:

    .flatMap(m -> m.entrySet().stream())
    
    1=[cell11, cell12, cell13],
    2=[cell21, cell22, cell23],
    ...
    

    过滤掉不包含以文本为给定字符串的单元格的值:
    如果找到任何值,findAny() 返回 Optional(不确定这是否是要求)

    .filter(containsCellWithText).findAny()
    
    

    上述谓词的实现:

    Predicate<Map.Entry> containsCellWithText = (Map.Entry me) -> me.getValue()
                                                                    .stream()
                                                                    .anyMatch(cell -> getTextFromElement(cell).equals(stringFirst));
    

    现在,只剩下所需的条目。获取对应索引的结果:

    .map(me -> driver.findElement(By.xpath(String.format("//table[@id='dt']/tbody/tr[%s]/td[%s]", me.getKey(), integerFirst))))
    

    我们应该在 Optional(如果存在)中得到答案。获取它,否则得到一个空字符串:

    .orElse("")
    

    完整答案汇总:

    List<WebElement> tableRows = driver.findElements(By.xpath("//table[@id='dt']/tbody/tr"));
            
    Predicate<Map.Entry> containsCellWithText = (Map.Entry me) -> me.getValue()
                                                                    .stream()
                                                                    .anyMatch(cell -> getTextFromElement(cell).equals(stringFirst));
            
    IntStream.rangeClosed(1,tableRows.size())
             .boxed()
             .map(idx -> Map.of(idx, list.get(idx-1).findElements(By.tagName("td"))))
             .flatMap(m -> m.entrySet().stream())
             .filter(containsCellValue)
             .findAny()
             .map(me -> driver.findElement(By.xpath(String.format("//table[@id='dt']/tbody/tr[%s]/td[%s]", me.getKey(), integerFirst))))
             .orElse("")
    

    资源:

    【讨论】:

    • 请注意,像 Map.of() 这样的一些操作适用于 Java 9 及以上版本
    【解决方案2】:

    这并不是您在这里要问的,但是当您尝试从每一行获取“tableCells”时,我很确定这不会达到您的预期。

    List<WebElement> tableCells = row.findElements(By.tagName("td"));
    

    它实际上并不在此特定行内搜索 td 元素,而是在整个页面上搜索。
    要在特定行中获取td,您必须使用以下命令:

    List<WebElement> tableCells = row.findElements(By.xpath(".//td"));
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-11-05
      • 1970-01-01
      相关资源
      最近更新 更多