2016-12-10 9 views
1

В моем приложении я использую метод scrape(string url) для очистки ссылок с веб-страницы. Допустим, он возвращает мне 10 URL каждый раз.Foreach внутри foreach внутри foreach

Я хотел бы очистить 10 ссылок от каждого исправленного URL.

Короче говоря:

(шаг 1) перейти на веб-страницу и царапать 10 ссылок

(этап 2) Еогеасп ссылку с шага 1 перейти на веб-страницу и царапать 10 ссылок

(шаг 3) для каждой ссылки с шага 2 перейдите на веб-страницу и соскрести 10 ссылок.

Так что это даст мне 10 + 100 + 1000 = 1110. ссылки

Конечно, я мог бы сделать что-то вроде этого:

List<string> links1 = new List<string>(); 
    List<string> links2 = new List<string>(); 
    List<string> links3 = new List<string>(); 


    links1 = scrape("example.com"); //get 10 links 

    foreach (string link in links1) 
    { 
     List<string> temp = new List<string>(); 
     temp = scrape(link); 
     links2.AddRange(temp); 
    } //get 100 links 

    foreach (string link in links2) 
    { 
     List<string> temp = new List<string>(); 
     temp = scrape(link); 
     links3.AddRange(temp); 
    } // get 1000 links 

Но это ужасно редактировать. Что, если я хотел бы очистить от царапаемых ссылок 10 раз? Я должен был бы сделать 10 foreach петель.

Можете ли вы дать мне какие-либо советы?

+0

Вы должны рекурсивную функцию для этого, я думаю. –

ответ

3

Рекурсивная функция будет вашим лучшим выбором. Тем не менее, вам нужно передать параметр, чтобы отслеживать «насколько глубоко» вы находитесь в своей царапине, или вы можете обходить весь общедоступный веб-сайт.

public List<string> GetLinks(List<string> urls, int depth){ 
    var newUrls = new List<string>(); 
    if(depth == 0) return newUrls ; 
    foreach(var url in urls){ 
     newUrls.AddRange(scrape(url)); 
    } 
    return urls.AddRange(GetLinks(newUrls, depth - 1); 
} 
+0

Это сработает, но было бы разумно, что для такого рода задач нужно написать что-то, что позволит параллельно обрабатывать. – Thomas

+0

@Thomas - Конечно, есть способы сделать это быстрее и лучше, но это не было целью вопроса :) Мы просто хотим помочь OP выбраться из 'foreach' ад! Экспериментально, 'Parallel.Foreach()' может работать, но его в каждом конкретном случае не имеет смысла включать. – Tommy

+0

Я удалил 'function', и он говорит:« Невозможно неявно преобразовать тип «void» в «System.Collections.Generic.List » – Dawvawd

1

Вам необходимо использовать рекурсию.

Идея здесь состоит в том, чтобы продолжать ссылаться на ту же функцию, пока не осталось детей. Примером рекурсии внутри FindTreeNode в функции TreeList:

TreeListNode FindTreeNode(TreeListNode node, Enumerations.ItemType type, Nullable<long> id) 
{ 
    foreach (var c in node.Nodes) 
    { 
     if ((Enumerations.ItemType)c[2] == type && 
      (id == null || (long)c[0] == id.Value)) { 

      return c; 
     } 

     if (c.HasChildren) 
     { 
      // Here is the secret sauce 
      // This is recursion 
      var exists = FindTreeNode(c, type, id); 
      if (exists != null) { return exists; } 
     } 
    } 
    return null; 
} 

Та же самая идея, как указано выше, за исключением того, в вашем случае это с веб-URI

Смежные вопросы