-1

文字列のコレクションがあります:

"Alberton;Johannesburg"
"Allendale;Phoenix"
"Brackenhurst;Alberton"
"Cape Town;"
"Durban;"
"Johannesburg;"
"Mayville;Durban"
"Phoenix;Durban"
"Sandton;Johannesburg"

次のように、可能な限り最速の方法で階層構造に構造化したいと考えています。

  • ヨハネスブルグ

    • アルバートン
      • ブラッケンハースト
    • サントン
  • ケープタウン

  • ダーバン

    • フェニックス
      • アランデール
    • メイビル

現在、forループとチェックをネストしていますが、単一のLAMBDAクエリでこれを実現できることを望んでいましたか?

上記の文字列はリストにあります。

4

2 に答える 2

1

特定のデータ構造を指定していないので、それ自体の子のリストを持つ Area というクラスを使用しました。また、linq の 2 行にあります。コードのように、領域が 2 つの別々の親の子であるかどうかを確認するチェックもありません。私が使用したテストのコードは次のとおりです(等号コメント間の関連行):

[TestFixture]
public class CitiesTest
{
    [Test]
    public void Test()
    {
        var strings = new List<string>
            {
                "Alberton;Johannesburg",
                "Allendale;Phoenix",
                "Brackenhurst;Alberton",
                "Cape Town;",
                "Durban;",
                "Johannesburg;",
                "Mayville;Durban",
                "Phoenix;Durban",
                "Sandton;Johannesburg"
            };

        //===================================================
        var allAreas = strings.SelectMany(x=>x.Split(';')).Where(x=>!string.IsNullOrWhiteSpace(x)).Distinct().ToDictionary(x=>x, x=>new Area{Name = x});

        strings.ForEach(area =>
            {
                var areas = area.Split(';');

                if (string.IsNullOrWhiteSpace(areas[1]))
                    return;

                var childArea = allAreas[areas[0]];
                if (!allAreas[areas[1]].Children.Contains(childArea))
                    allAreas[areas[1]].Children.Add(childArea);

                childArea.IsParent = false;
            });

        var result = allAreas.Select(x=>x.Value).Where(x => x.IsParent);
        //===================================================
    }

    public class Area
    {
        public string Name;
        public bool IsParent;
        public List<Area> Children { get; set; }

        public Area()
        {
            Children = new List<Area>();
            IsParent = true;
        }
    }
}
于 2013-03-15T11:52:47.707 に答える
1

ラムダのようなソリューションを用意しましたが、現在のソリューションよりも読みやすく/効率的であるかどうかを実際に検討する必要があります。

ヘルパー拡張方法:

public static class ChildrenGroupExtensions
{
    public static List<CityInfo> GetChildren(this IEnumerable<IGrouping<string, City>> source, string parentName)
    {
        var cities = source.SingleOrDefault(g => g.Key == parentName);
        if (cities == null)
            return new List<CityInfo>();

        return cities.Select(c => new CityInfo { Name = c.Name, Children = source.GetChildren(c.Name) }).ToList();
    }
}

ヘルパー クラス:

public class City
{
    public string Name { get; set; }
    public string Parent { get; set; }
}

public class CityInfo
{
    public string Name { get; set; }
    public List<CityInfo> Children { get; set; }
}

使用法:

var groups = (from i in items
                let s = i.Split(new[] { ';' })
                select new City { Name = s[0], Parent = s[1] }).GroupBy(e => e.Parent);


var root = groups.GetChildren(string.Empty);

itemsあなたはどこですかList<string>

次のような単純なヘルパー メソッドで結果を確認できます。

private static void PrintTree(List<CityInfo> source, int level)
{
    if (source != null)
    {
        source.ForEach(c =>
        {
            Enumerable.Range(1, level).ToList().ForEach(i => Console.Write("\t"));
            Console.WriteLine(c.Name);
            PrintTree(c.Children, level + 1);
        });
    }
}

結果は次のとおりです。

Cape Town
Durban
        Mayville
        Phoenix
                Allendale
Johannesburg
        Alberton
                Brackenhurst
        Sandton
于 2013-03-15T11:53:27.503 に答える