C# 重复linq查询几次
这个问题与上一个问题有关 我正在努力让这个代码正常工作。我的意图是使用Linq查询将可见项从web表添加到对象。Web表是动态加载的,所以在滚动时,它会加载项目,同时卸载其他项目。加载页面后直接向下滚动不是一个选项 我有几个问题:C# 重复linq查询几次,c#,linq,selenium,C#,Linq,Selenium,这个问题与上一个问题有关 我正在努力让这个代码正常工作。我的意图是使用Linq查询将可见项从web表添加到对象。Web表是动态加载的,所以在滚动时,它会加载项目,同时卸载其他项目。加载页面后直接向下滚动不是一个选项 我有几个问题: Linq查询是否可以通过这种方式完成(添加可见项、滚动、添加可见项等) 如何将DataHereH转换为ListDataHere 这是我目前的代码: public static IEnumerable<UserTableRow> AddItemsT
DataHereH
转换为ListDataHere
public static IEnumerable<UserTableRow> AddItemsToList(IWebDriver driver)
{
IReadOnlyCollection<IWebElement> rows = new List<IWebElement>();
object DataHereH;
driver.FindElement(By.XPath("//*[@id=\"users_table\"]/div[5]/div/div[1]")).Click();
for (int i = 0; i < 4; i++)
{
rows = driver.FindElements(By.CssSelector("#users_table .slick-viewport .slick-row"));
// This part will get our first visible items in table to list, after page load
DataHereH = from row in rows
select new UserTableRow(row);
Actions actions = new Actions(driver);
actions.SendKeys(Keys.PageDown).Build().Perform();
}
List<UserTableRow> noDupes = DataHere.Distinct().ToList();
return noDupes;
}
你可以用发电机来做这个
公共静态IEnumerable AddItemsToList(IWebDriver驱动程序)
{
var uniqueData=new HashSet();
var动作=新动作(驱动因素);
driver.findelelement(By.XPath(“//*[@id=\“users\u table\”]/div[5]/div/div[1]”)。单击();
对于(int i=0;i<4;i++)
{
var latestElements=driver.FindElements(By.CssSelector(“#users_table.slick viewport.slick row”);
foreach(后期元素中的var元素)
{
var row=新的UserTableRow(元素);
var isUnique=uniqueData.Add(行);
如果(isUnique)收益率返回行;
}
actions.SendKeys(Keys.PageDown).Build().Perform();
}
}
但请注意,在这种情况下以及Linq的Distinct
情况下,您需要提供一个使用值相等的对象
当前,您的UserTableRow
类使用引用相等,因此您将收到重复的引用
要缓解此问题,您可以执行以下操作之一:
- 实施价值比较:
- 如果selenium驱动程序使用值相等或具有一些内部缓存,则可以将哈希集更改为跟踪unique
IWebElement
公共抽象类ValueObject
{
受保护的静态布尔均衡器(ValueObject左、ValueObject右)
{
if(ReferenceEquals(左,空)^ReferenceEquals(右,空))
{
返回false;
}
返回ReferenceEquals(左,空)| |左。Equals(右);
}
受保护的静态布尔NotEqualOperator(ValueObject左、ValueObject右)
{
返回!(均衡器(左、右));
}
受保护的抽象IEnumerable GetAtomicValues();
公共覆盖布尔等于(对象对象对象)
{
if(obj==null | | obj.GetType()!=GetType())
{
返回false;
}
ValueObject其他=(ValueObject)对象;
IEnumerator thisValues=GetAtomicValues().GetEnumerator();
IEnumerator otherValues=other.GetAtomicValues().GetEnumerator();
while(thisValues.MoveNext()&&otherValues.MoveNext())
{
if(ReferenceEquals(thisValues.Current,null)^
ReferenceEquals(otherValues.Current,null))
{
返回false;
}
如果(thisValues.Current!=null&&
!thisValues.Current.Equals(otherValues.Current))
{
返回false;
}
}
return!thisValues.MoveNext()&&!otherValues.MoveNext();
}
公共覆盖int GetHashCode()
{
返回GetAtomicValues()
.Select(x=>x!=null?x.GetHashCode():0)
.骨料((x,y)=>x^y);
}
//其他实用方法
}
然后您可以重新定义UserTableRow
,如下所示:
公共类UserTableRow:ValueObject
{
公共字符串用户名{get;private set;}
公共字符串名{get;private set;}
公共字符串Lastname{get;private set;}
公共字符串类型{get;private set;}
公共字符串组{get;private set;}
公共字符串JobTitle{get;private set;}
公共字符串DefaultPrice{get;private set;}
公共字符串未来{get;private set;}
公共字符串语言{get;private set;}
公共用户表行(IWebElement行)
{
Username=row.FindElement(By.XPath(“.//div[contains(@class,'slick cell l0 r0')]”);
Firstname=row.FindElement(By.XPath(“.//div[contains(@class,'slick cell l1 r1')])))。文本;
LastName=row.FindElement(By.XPath(“.//div[contains(@class,'slick cell l2 r2')])))。文本;
Type=row.FindElement(By.XPath(“.//div[contains(@class,'slick cell l3 r3')]”);
Crew=row.FindElement(By.XPath(“.//div[contains(@class,'slick cell l4 r4')])))。文本;
JobTitle=row.FindElement(By.XPath(“.//div[contains(@class,'slick cell l5 r5')]”);
DefaultPrice=row.FindElement(By.XPath(“.//div[contains(@class,'slick cell l6 r6')]”);
Future=row.FindElement(By.XPath(“.//div[contains(@class,'slick cell l7 r7')]))));
Language=row.FindElement(By.XPath(“.//div[contains(@class,'slick cell l8 r8')]))))。文本;
}
受保护的重写IEnumerable GetAtomicValues()
{
返回用户名;
返回名字;
返回姓氏;
收益型;
返回机组;
收益回报率;
收益-回报-价格;
收益率-收益率-未来;
产生返回语言;
}
}
这具有实现值相等的优点,因此可以使用hashset删除重复项。但它的缺点是无法与元素交互,因为这将在构建时提供dom的形状快照
注意:使用C#9,这类事情会容易得多-请参阅记录您能为表格添加HTML吗?@GregBurghardt这仍然是本文中的表格。这很好,但是你当前的问题应该包含人们回答它所需要的一切,而不必在前面的问题中四处寻找。@GregBurghardt问题编辑谢谢你!这是有效的
public class UserTableRow
{
private readonly IWebElement row;
public string Username => row.FindElement(By.XPath(".//div[contains(@class, 'slick-cell l0 r0')]")).Text;
public string Firstname => row.FindElement(By.XPath(".//div[contains(@class, 'slick-cell l1 r1')]")).Text;
public string Lastname => row.FindElement(By.XPath(".//div[contains(@class, 'slick-cell l2 r2')]")).Text;
public string Type => row.FindElement(By.XPath(".//div[contains(@class, 'slick-cell l3 r3')]")).Text;
public string Crew => row.FindElement(By.XPath(".//div[contains(@class, 'slick-cell l4 r4')]")).Text;
public string JobTitle => row.FindElement(By.XPath(".//div[contains(@class, 'slick-cell l5 r5')]")).Text;
public string DefaultPrice => row.FindElement(By.XPath(".//div[contains(@class, 'slick-cell l6 r6')]")).Text;
public string Future => row.FindElement(By.XPath(".//div[contains(@class, 'slick-cell l7 r7')]")).Text;
public string Language => row.FindElement(By.XPath(".//div[contains(@class, 'slick-cell l8 r8')]")).Text;
public override string ToString()
{
return "SharePrice: " + Username.ToString() + ": " + Firstname.ToString();
}
public UserTableRow(IWebElement row)
{
try
{
this.row = row;
}
catch (Exception)
{
throw;
}
}
}