C# foreach

electro

Client
Регистрация
08.08.2015
Сообщения
98
Благодарностей
14
Баллы
8
Код:
Tab olx = instance.ActiveTab;
if (olx.IsBusy)
{
    olx.WaitDownloading();
}
HtmlElementCollection AdCollection = olx.FindElementsByXPath("//tr[starts-with(@class, 'tr row-elem')]");
List<string> GoodTitle = project.Lists["Нужные строки"].ToList();
foreach (HtmlElement Ad in AdCollection)
{
    var title = Ad.FindChildByAttribute("h3", "class", "normal brkword fbold", "regexp", 0);
    string strListElement = GoodTitle.First();
    if (title.GetAttribute("title").Contains(strListElement))
    {
        project.SendInfoToLog(title.GetAttribute("title"));
        GoodTitle.RemoveAt(0);
    }
}
Почему не работает цикл? В лог выводится только один элемент, хотя по идее кубик должен удалить первую строку, взять следующую и вывести в лог уже другой. Помогите пожалуйста, на форуме я решение не нашел, сам додуматься не могу.
 

shade

Client
Регистрация
19.11.2010
Сообщения
580
Благодарностей
346
Баллы
63

electro

Client
Регистрация
08.08.2015
Сообщения
98
Благодарностей
14
Баллы
8
Дело не в этом, ибо если вставить project.SendInfoToLog(title.GetAttribute("title")) раньше if, то в лог выводит вообще все нужные элементы со страницы.
П.С: Я попробовал, не помогло, но все равно спасибо за то что откликнулись)
 

shade

Client
Регистрация
19.11.2010
Сообщения
580
Благодарностей
346
Баллы
63
Дело не в этом, ибо если вставить project.SendInfoToLog(title.GetAttribute("title")) раньше if, то в лог выводит вообще все нужные элементы со страницы.
П.С: Я попробовал, не помогло, но все равно спасибо за то что откликнулись)
Тогда получается что условие
Код:
if (title.GetAttribute("title").Contains(strListElement))
как то не так работает.

Но мне кажется что код должен быть такой
Код:
foreach (HtmlElement Ad in AdCollection)
{
    var title = Ad.FindChildByAttribute("h3", "class", "normal brkword fbold", "regexp", 0);
    string strListElement = GoodTitle.First();
    if (title.GetAttribute("title").Contains(strListElement)) project.SendInfoToLog(title.GetAttribute("title"));
    GoodTitle.RemoveAt(0);
}
Если я правильно понял логику.
 
  • Спасибо
Реакции: electro

electro

Client
Регистрация
08.08.2015
Сообщения
98
Благодарностей
14
Баллы
8
Тогда получается что условие
Код:
if (title.GetAttribute("title").Contains(strListElement))
как то не так работает.

Но мне кажется что код должен быть такой
Код:
foreach (HtmlElement Ad in AdCollection)
{
    var title = Ad.FindChildByAttribute("h3", "class", "normal brkword fbold", "regexp", 0);
    string strListElement = GoodTitle.First();
    if (title.GetAttribute("title").Contains(strListElement)) project.SendInfoToLog(title.GetAttribute("title"));
    GoodTitle.RemoveAt(0);
}
Если я правильно понял логику.
В чем разница между вариантами? В том что RemoveAt(0) вне If?
Выдает ошибку - "Последовательность не содержит элементов".
 

Moadip

Client
Регистрация
26.09.2015
Сообщения
509
Благодарностей
823
Баллы
93
В чем разница между вариантами? В том что RemoveAt(0) вне If?
Выдает ошибку - "Последовательность не содержит элементов".
Разница огромна. В вашем варианте идет удаление из коллекции только при выполнении условия.
В варианте который предложил shade в любом случае.
А ошибка возникает из за того, что если AdCollection имеет больше элементов чем GoodTitle то наступает момент, когда в GoodTitle уже пусто но вызывается удаление элемента по индексу 0.

Вы бы описали что вам надо.
Я так понял у вас есть список GoodTitle и вам надо из него удалить строчки, которые есть в AdCollection вытащенные из атрибута title, все верно?
 

electro

Client
Регистрация
08.08.2015
Сообщения
98
Благодарностей
14
Баллы
8
Разница огромна. В вашем варианте идет удаление из коллекции только при выполнении условия.
В варианте который предложил shade в любом случае.
А ошибка возникает из за того, что если AdCollection имеет больше элементов чем GoodTitle то наступает момент, когда в GoodTitle уже пусто но вызывается удаление элемента по индексу 0.

Вы бы описали что вам надо.
Я так понял у вас есть список GoodTitle и вам надо из него удалить строчки, которые есть в AdCollection вытащенные из атрибута title, все верно?
Ну это понятно.
Да, мне нужно просто удалить строку из списка, если выполнено условие.
>Вы бы описали что вам надо.
>кубик должен удалить первую строку, взять следующую и вывести в лог уже другой.
 

shade

Client
Регистрация
19.11.2010
Сообщения
580
Благодарностей
346
Баллы
63
В чем разница между вариантами? В том что RemoveAt(0) вне If?
Выдает ошибку - "Последовательность не содержит элементов".
Тогда так:
Код:
foreach (HtmlElement Ad in AdCollection)
{
    if (GoodTitle.Count == 0) break;
    var title = Ad.FindChildByAttribute("h3", "class", "normal brkword fbold", "regexp", 0);
    string strListElement = GoodTitle.First();
    if (title.GetAttribute("title").Contains(strListElement)) project.SendInfoToLog(title.GetAttribute("title"));
    GoodTitle.RemoveAt(0);
}
Разница огромна. В вашем варианте идет удаление из коллекции только при выполнении условия.
В варианте который предложил shade в любом случае.
А ошибка возникает из за того, что если AdCollection имеет больше элементов чем GoodTitle то наступает момент, когда в GoodTitle уже пусто но вызывается удаление элемента по индексу 0.

Вы бы описали что вам надо.
Я так понял у вас есть список GoodTitle и вам надо из него удалить строчки, которые есть в AdCollection вытащенные из атрибута title, все верно?
Тогда вот так:

Код:
foreach (HtmlElement Ad in AdCollection)
{
    if (GoodTitle.Count == 0) break;
    var title = Ad.FindChildByAttribute("h3", "class", "normal brkword fbold", "regexp", 0);
   
    string forRemove = String.Empty;
    foreach (string strListElement in GoodTitle)
    {
        if (title.GetAttribute("title").Contains(strListElement)) 
        {
            project.SendInfoToLog(title.GetAttribute("title"));
            forRemove = strListElement;
            break;
        }
    }
   
    if (forRemove != String.Empty) GoodTitle.Remove(forRemove);
   
}
P.S. Пишу код прямо здесь могут быть ошибки :-)
 

Moadip

Client
Регистрация
26.09.2015
Сообщения
509
Благодарностей
823
Баллы
93
>кубик должен удалить первую строку, взять следующую и вывести в лог уже другой.
Если именно в таком формате, то shade предложил правильный вариант.

Delete.

Еще раз перечитал, но так и не понял что надо сделать.:-)
 
  • Спасибо
Реакции: shade

electro

Client
Регистрация
08.08.2015
Сообщения
98
Благодарностей
14
Баллы
8
Если именно в таком формате, то shade предложил правильный вариант.



Из GoodTitle будут удаляться строчки, соответствующие условию, до тех пор пока список не пустой.
В лог всегда будет выводится нова строчка из AdCollection.
Этого не происходит, ну и вообще код по ошибке отрабатывает из-за того что строк в списке не хватает. Он должен удалять, только если условие выполнено, это же видно, ибо у меня в изначальном коде RemoveAt(0) внутри If, а не снаружи, но в этом случае кубик просто не берет следующий заголовок, что-то не так с RemoveAt(0) или с моими руками.
 

Moadip

Client
Регистрация
26.09.2015
Сообщения
509
Благодарностей
823
Баллы
93
Еще раз. Есть список AdCollection, мы начинаем проходиться по нему.
Берем из GoodTitle строчку, если она соответствует условию, то удаляем. С этим вроде разобрались.

В лог то что должно выводиться?
Любая строчка из AdCollection или только если выполнилось условие?
 

electro

Client
Регистрация
08.08.2015
Сообщения
98
Благодарностей
14
Баллы
8
Еще раз. Есть список AdCollection, мы начинаем проходиться по нему.
Берем из GoodTitle строчку, если она соответствует условию, то удаляем. С этим вроде разобрались.

В лог то что должно выводиться?
Любая строчка из AdCollection или только если выполнилось условие?
Только если выполнилось.
В общем, на странице есть элемент с атрибутом title, нужно кликнуть по кнопке рядом с ним, если атрибут title совпадает с строкой из списка(это я в состоянии написать сам), и удалить эту строку(это не в состоянии) Как я понимаю, строка просто не удаляется, или if не идет на второе выполнение.
 

Moadip

Client
Регистрация
26.09.2015
Сообщения
509
Благодарностей
823
Баллы
93
Только если выполнилось.
Ну тогда у вас все правильно в самом вашем первом посте, за исключением того, что нет проверки, есть ли элементы в GoodTitle.

Идет проход по AdCollection, на каждой итерации берется первая строка из GoodTitle, если выполнилось условие, то строка удаляется и в лог выводится мессага.
Все. Если условие не выполнилось, то не удаляться и в лог ничего выводиться не будет.

Тогда все правильно, вот это то что предложил shade и то что я потер, т.к. думал что не правильно, все таки правильно.:-)

UPD: подправил чутка. Теперь именно так, как вы описываете.
UPD2: нужна еще проверка чтобы дочерний элемент вообще находился.

Код:
foreach (HtmlElement Ad in AdCollection)
{
    if (GoodTitle.Count == 0) 
        break;

    var title = Ad.FindChildByAttribute("h3", "class", "normal brkword fbold", "regexp", 0);
    var strListElement = GoodTitle.First();
    
    if (!title.IsNull && title.GetAttribute("title").Contains(strListElement))
    {
        project.SendInfoToLog(title.GetAttribute("title"));
        GoodTitle.RemoveAt(0);
    }
}
По AdCollection есть смысл делать проходы, только тогда, когда в GoodTitle есть строчки, иначе смысла нет во всех остальных сравнениях.

А дальше, именно то что вам надо, выполнилось условие - вывели в лог и удалили строчку из GoodTitle.
Если вам кажется что как то не так работает, то исходя из того что вы пишете, работает все так как надо.
Но если все таки не так как надо, то тут только один вариант - в AdCollection нет нужных элементов.
 
Последнее редактирование:

electro

Client
Регистрация
08.08.2015
Сообщения
98
Благодарностей
14
Баллы
8
Вот скрин списка
Скрин111.png

Вот скрины результата прогона кубика с project.SendInfoToLog(title.GetAttribute("title")); вне If, для того чтобы убедиться что элементы с таким атрибутом title есть на странице:
Скрин222.png


Скрин333.png


Вот результат прогона кубика с project.SendInfoToLog(title.GetAttribute("title")); внутри If:
Скрин444.png

Вот.
 

Moadip

Client
Регистрация
26.09.2015
Сообщения
509
Благодарностей
823
Баллы
93
Понятно.
Ну тут только один вариант, значит строчка из GoodTitle не совпадает с title из AdCollection.
Скорее всего возможно пробел лишний с края или там или там.
Попробуйте сделать Trim() для элементов и там и там.

Код:
var title = Ad.FindChildByAttribute("h3", "class", "normal brkword fbold", "regexp", 0).Trim();
var strListElement = GoodTitle.First().Trim();
Если не поможет, ну тогда значит открывать логи, вытаскивать оттуда строчки, которые пишутся в логе, и которые нужны.
И сравнивать их побуквенно в каком то редакторе со строчками из GoodTitle.

Вот толковая прога для этого, пользуюсь уже давно. Да еще и бесплатная(бесплатного варианта вполне хватает).
https://www.devart.com/codecompare/

UPD: И да. Еще один нюанс.
Вот взялась первая строка из GoodTitle, дальше идет проход по AdCollection, нашли, удалили, взяли следующую строку из GoodTitle но она вполне уже может не найтись, т.к. она уже давным давно была пройдена.

Но судя по времени в логе вроде все ок, первая строка из GoodTitle появляется раньше чем вторая.

Но имхо, это хреновый расклад. Если надо чтобы однозначно если строки из GoodTitle есть в AdCollection удалялись, то надо делать не так.
 
Последнее редактирование:
  • Спасибо
Реакции: electro

electro

Client
Регистрация
08.08.2015
Сообщения
98
Благодарностей
14
Баллы
8
Понятно.
Ну тут только один вариант, значит строчка из GoodTitle не совпадает с title из AdCollection.
Скорее всего возможно пробел лишний с края или там или там.
Попробуйте сделать Trim() для элементов и там и там.

Код:
var title = Ad.FindChildByAttribute("h3", "class", "normal brkword fbold", "regexp", 0).Trim();
var strListElement = GoodTitle.First().Trim();
Если не поможет, ну тогда значит открывать логи, вытаскивать оттуда строчки, которые пишутся в логе, и которые нужны.
И сравнивать их побуквенно в каком то редакторе со строчками из GoodTitle.

Вот толковая прога для этого, пользуюсь уже давно. Да еще и бесплатная(бесплатного варианта вполне хватает).
https://www.devart.com/codecompare/

UPD: И да. Еще один нюанс.
Вот взялась первая строка из GoodTitle, дальше идет проход по AdCollection, нашли, удалили, взяли следующую строку из GoodTitle но она вполне уже может не найтись, т.к. она уже давным давно была пройдена.

Но судя по времени в логе вроде все ок, первая строка из GoodTitle появляется раньше чем вторая.

Но имхо, это хреновый расклад. Если надо чтобы однозначно если строки из GoodTitle есть в AdCollection удалялись, то надо делать не так.
Ну, спасибо за помощь)
 

electro

Client
Регистрация
08.08.2015
Сообщения
98
Благодарностей
14
Баллы
8
Понятно.
Ну тут только один вариант, значит строчка из GoodTitle не совпадает с title из AdCollection.
Скорее всего возможно пробел лишний с края или там или там.
Попробуйте сделать Trim() для элементов и там и там.

Код:
var title = Ad.FindChildByAttribute("h3", "class", "normal brkword fbold", "regexp", 0).Trim();
var strListElement = GoodTitle.First().Trim();
Если не поможет, ну тогда значит открывать логи, вытаскивать оттуда строчки, которые пишутся в логе, и которые нужны.
И сравнивать их побуквенно в каком то редакторе со строчками из GoodTitle.

Вот толковая прога для этого, пользуюсь уже давно. Да еще и бесплатная(бесплатного варианта вполне хватает).
https://www.devart.com/codecompare/

UPD: И да. Еще один нюанс.
Вот взялась первая строка из GoodTitle, дальше идет проход по AdCollection, нашли, удалили, взяли следующую строку из GoodTitle но она вполне уже может не найтись, т.к. она уже давным давно была пройдена.

Но судя по времени в логе вроде все ок, первая строка из GoodTitle появляется раньше чем вторая.

Но имхо, это хреновый расклад. Если надо чтобы однозначно если строки из GoodTitle есть в AdCollection удалялись, то надо делать не так.
Я победил Olx(ну или сам себя).
>она вполне уже может не найтись, т.к. она уже давным давно была пройдена.
this.
Получается, поидее, нужно сделать цикл в цикле, завести счетчик в кубике и переменную, которая будет отвечать за нужное количество строк
Допустим:
Код:
int Counter = 0; Counter++;
while (Counter < strCount)
{
    foreach (HtmlElement Ad in AdCollection)
    {
        var title = Ad.FindChildByAttribute("h3", "class", "normal brkword fbold", "regexp", 0);
        var button = Ad.FindChildByAttribute("span", "innertext", "Обновить", "regexp", 0);
        if (title.GetAttribute("title").Contains(strListElement))
        {
            project.SendInfoToLog(title.GetAttribute("title"));
            button.ScrollIntoView();
            System.Threading.Thread.Sleep(3500);
            button.Click();
            project.SendInfoToLog(button.GetAttribute("innerhtml"));
            GoodTitle.RemoveAt(0);
            Counter += 1;
        }
    }
}
Ну т.е если я правильно все понимаю, то если Counter будет равен 1 при том что strCount ровно 2, то кубик пойдет на второе выполнение foreach и все-таки выцепит нужный элемент.
Еще не проверял, пока нет возможности, писал прямо тут) Спасибо еще раз за помощь!
 
Последнее редактирование:

Кто просматривает тему: (Всего: 1, Пользователи: 0, Гости: 1)