

[![画像の説明をここに入力](https://i.stack.imgur.com/iBzmC.png)](https://i.stack.imgur.com/iBzmC.png)

あるデータをツリー構造のデータを作ろうとしているのですが、  
うまくロジックをくめずにおります。  
イメージとしては  
画像のようなA～Fのデータをツリーで持ちたく考えており、

データとしてA～Fをもつデータ配列と  
矢印線のデータ配列があります。  
A～Fのデータはそれぞれ、つながる線のデータをもち、  
矢印線のデータは矢印の先にどのデータA～Fにつながっているかの情報を持っています。

図のように矢印のデータにIN、OUTがわかるようであれば若干楽になるのですが  
それがない状態です。  
A～FのデータはAがトップのデータであるということのみがわかるようなものになっています。

[code]

    List<Item> items;   A～Fのリスト情報
    List<Arrow> arrows; 矢印線のリスト情報
    
    
        public class Element
        {
                public int Id;
                public int Parent;
                public IList Children;
        }
    
[/code]

～～

[code]

    ObservableCollection<Element> tree = new ObservableCollection<Element>();
    
    Element element = new Element();
    element.Id = items[0].Id;
    itemsからA（トップ）の情報を取得し、つながるアイテムデータのリストを取得する
    element.Childrenに取得したリストを設定
    // ツリー情報にエレメントを追加
    tree.Add(element);
    
[/code]

つながるアイテムデータのリスト分、同じような処理をループして行うことになると思うのですが、どのようにメソッドを分けていいのかが整理できずにおります。

説明が下手で申し訳ないのですが、アドバイスいただけると助かります。


CC BY-SA 4.0
2018-03-06T10:08:24.207
42165
2018-09-19T06:45:16.697
2018-09-19T06:45:16.697
19110
12842
question
c#
ツリー構造の情報を作りたい


ルートノードとエッジの有無のみが分かっているとのことですので、

[code]

    // Element root;
    // Element[] nodes;
    var done = new List<Element>() { root };
    var undone = nodes.Where(e => e != root).ToList();
    
[/code]

のような要領で処理済み・未処理のコレクションを用意し、順次親子関係を対応させながら移していく形が良いと思います。

[code]

    // 未処理ノードが存在する間繰り返す
    while (undone.Any())
    {
        // 未処理ノードを一個ずつ取り出す
        for (var i = 0; i < undone.Count; i++)
        {
            var n = nodes[i];
    
            var parent = done.FirstOrDefault(e => エッジがあるか判定(e, n));
    
            if (parent != null)
            {
                // 親が処理済みノードに見つかった場合は各プロパティを設定する
                parent.Children.Add(n);
                n.Parent = parent;
    
                // 処理済みノードに移動する
                done.Add(n);
                undone.RemoveAt(i);
    
                break;
            }
        }
    }
    
[/code]

なお`Element`型の`Parent`は`Element`型、`Children`は`Collection<Element>`型にし、継承して`AddItem`他のメソッドをオーバーライドし、`Parent`が自動設定されるようにする設計が良いと思います。

[code]

    public class Element
    {
        public int Id;
        public Element Parent { get; private set; }
    
        private Collection<Element> _Children;
        public Collection<Element> Children
            => _Children ?? (_Children = new ElementCollection(this));
    
        private class ElementCollection : Collection<Element>
        {
            private readonly Element Parent;
            public ElementCollection(Element parent)
            {
                Parent = parent;
            }
    
            protected override AddItem(int index, Element item)
            {
                if (item.Parent != null)
                {
                    throw new InvalidOperationException();
                }
                item.Parent = Parent;
                super.AddItem(index, item);
            }
            // TODO: SetItem, RemoveItem, ClearItemも実装する
        }
    }
    
[/code]


CC BY-SA 3.0
2018-03-06T10:53:29.713
42169
2018-03-06T10:53:29.713
5750
42165
answer