Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > .NET для новичков > Построить дерево


Автор: W1zArD 7.1.2010, 23:42
Добрых суток.

Совсем запутался, точнее понял в чем проблема, но как решить ее, уже нет сил.
На часах 2:40, а времени все меньше и меньше. Буду рад помощи.

Итак имеется код:

Файл Record.cs
Код

public class Record
        {
            public string Url;
            public List<Record> Pages { get; set; }

            public Record(string url, List<Record> pages)
            {
                Url = url;
                Pages = pages;
            }

            public Record() : this("/", new List<Record>()) { }
        }


Файл Form1.cs
Код

private static Record Get(string fr, Record o)
        {
            foreach(var a in o.Pages)
            {
                if (a.Url == fr)
                {
                    return a;
                }
                var ab = Get(fr, a);
                if (ab != null)
                {
                    return ab;
                }
            }
            return null;
        }

        private static Record MakeTree(IEnumerable<Uri> list)
        {
            var result = new Record();
            foreach (var page in list)
            {
                var level = 0;
                foreach (var segment in page.Segments)
                {
                    if (segment == "/")
                    {
                        continue;
                    }
                    string print = level == 0 ? segment : page.Segments[level];
                    Record x = Get(print, result);
                    if (x != null)
                    {
                        if (x.Url == segment)
                        {
                            level++;
                            continue;
                        }
                        var wo = new Record(segment, new List<Record>());
                        if (!x.Pages.Exists(a => a.Url == wo.Url))
                        {
                            x.Pages.Add(wo);
                        }
                    }
                    else
                    {
                        result.Pages.Add(new Record(segment, new List<Record>()));
                    }
                    level++;
                }
            }
            return result;
        }


Вроде бы все хорошо, но если скормить ссылки к примеру:
http://site.com/abc/cba/test.php
и 
http://site.com/abc2/cba/test2.php

то у меня получится примерно так:
/
-abc
--cba
---test.php
---test2.php
--abc2
---cba

вобщем получается что найдя первое совпадение, метод Get возвращает первый попавшийся объект для которого Url совпало по условию.

Как сделать правильно?
Цель задачи, построить Карту Сайта по заданной коллекции ссылок.

Благодарю за внимание.

Автор: W1zArD 10.1.2010, 17:29
неужели никто?  smile 

Автор: tol05 10.1.2010, 19:18
ошибка в методе Get - хотя "cba" и будет присутствовать в обеих подветвях - он всегда возвращает только первое совпадение по значению сегмента, независимо от того, какая Page сейчас обрабатывается. Текстовые Pages и сегменты меняются, а иерархии Records - не переключаются. Значит нужно указывать Page, где методу Get нужно искать

вот подправленный код.
Цитата

private static Record MakeTree(IEnumerable<Uri> list)
  {
    var result = new Record();
    int pageIndex = 0;
    foreach (var page in list)
    {
    var level = 0;
    foreach (var segment in page.Segments)
    {
     if (segment == "/")
     {
      continue;
     }
     string print = level == 0 ? segment : page.Segments[level];
     Record x = Get(print, result, pageIndex);
     if (x != null)
     {
      if (x.Url == segment)
      {
       level++;
       continue;
      }
      var wo = new Record(segment, new List<Record>());
      if (!x.Pages.Exists(a => a.Url == wo.Url))
      {
       x.Pages.Add(wo);
      }
     }
     else
     {
      result.Pages.Add(new Record(segment, new List<Record>()));
     }
     level++;
    }
    pageIndex++;
    }
    return result;
  }
    }

private static Record Get(string fr, Record o, int pageIndex)
  {
    if (o.Pages.Count == 0 || o.Pages.Count <= pageIndex)
    {
    return null;
    }
    Record a = o.Pages[pageIndex];

    if (a.Url == fr)
    {
    return a;
    }
    var ab = Get(fr, a, 0);
    if (ab != null)
    {
    return ab;
    }
    
    return null;
  }


хотя конечно я бы подумал над перепроектированием этих методов - они читаются очень тяжело. Я бы подумал над переносом метода Get в класс Record и удерживании ссылки на текущую иерархию Records, которая в данный момент обрабатывается

Автор: W1zArD 11.1.2010, 19:04
tol05, благодарю за ответ. В действительности все работает, почти.
Дело в том что создаются элементы с одинаковым Url.
Думаю понятнее будет на http://img340.imageshack.us/img340/9809/01112010220159.jpg

Ссылки для примера:
http://site.com/Content/Css/General.css
http://site.com/Content/Css/General.css
http://site.com/rss/Content/Css/General.css
http://site.com/rss/Content/Css/Print.css

У меня складывается впечатление что выбран неверный подход и я все это время просто извращался...

Автор: tol05 13.1.2010, 14:28
W1zArD, я бы сделал так примерно
Код

internal class Program
    {
        private static void Main(string[] args)
        {
            List<Uri> uris = new List<Uri>
                              {
                                  new Uri("http://site.com/Content/Css/General.css"),
                                  new Uri("http://site.com/Content/Css/General.css"),
                                  new Uri("http://site.com/rss/Content/Css/General.css"),
                                  new Uri("http://site.com/rss/Content/Css/Print.css")
                              };

            Record root = new Record(uris[0].Authority);    //  "site.com"
            root.MakeTree(uris);
        }
    }

    public class Record
    {
        public List<Record> Pages { get; set; }
        public string SegmentName { get; set; }

        public Record(string segmentName)
        {
            SegmentName = segmentName;
            Pages = new List<Record>();
        }

        public void MakeTree(List<Uri> uris)
        {
            foreach (Uri uri in uris)
            {
                if (uri.Authority != SegmentName)
                {
                    continue; // url не относится к сайту
                }

                List<string> segments = new List<string>(uri.AbsolutePath.Split('/'));
                segments.RemoveAt(0);    
                                                                 
                InnerMakeTree(segments);
            }
        }

        private void InnerMakeTree(List<string> segments)
        {
            string segmentName = segments[0];

            Record childPage = GetPage(segmentName);

            if (segments.Count == 1)
            {
                return; //конец рекурсии
            }

            segments.Remove(segmentName);

            childPage.InnerMakeTree(segments);
        }

        private Record GetPage(string pageName)
        {
            Record childPage = Pages.Find(rec => rec.SegmentName == pageName);
            if (childPage == null)
            {
                childPage = new Record(pageName);
                Pages.Add(childPage);
            }

            return childPage;
        }
    }


Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)