63009


以下のように前行番号と後行番号を指示して並び替えたいです。どのようにすれば良いでしょうか。  
対象のフレームワークは.NET Framework 4.7.2で、IDEはVisual Studio Community 2019 Version
16.3.10です。  
OSは、Windows 10 1903です。

[code]

    static void Main(string[] args)
    {
        Dictionary<int, string> oldDictionary = new Dictionary<int, string>();
        oldDictionary.Add(1, "日本円");
        oldDictionary.Add(2, "アメリカドル");
        oldDictionary.Add(3, "オーストラリアドル");
        oldDictionary.Add(4, "ニュージーランドドル");
    
        foreach (var item in oldDictionary.OrderBy((x) => x.Key))
        {
            Console.WriteLine(item.Key + "_" + item.Value);
        }
    
        Dictionary<int, string> newDictionary = ChangeOrder(oldDictionary, 2, 4);
        foreach (var item in newDictionary.OrderBy((x) => x.Key))
        {
            Console.WriteLine(item.Key + "" + item.Value);
        }
        //欲しい結果（2番目のアメリカドルを4番目にする。あとは元の並び順通り）
        //1 日本円
        //2 オーストラリアドル
        //3 ニュージーランドドル
        //4 アメリカドル
    
        newDictionary = ChangeOrder(oldDictionary, 1, 3);
        foreach (var item in newDictionary.OrderBy((x) => x.Key))
        {
            Console.WriteLine(item.Key + "" + item.Value);
        }
        //欲しい結果（1番目の日本円を3番目にする。あとは元の並び順通り）
        //1 アメリカドル
        //2 オーストラリアドル
        //3 日本円
        //4 ニュージーランドドル
    
        Console.ReadLine();
    }
    
    static Dictionary<int, string> ChangeOrder(Dictionary<int, string> oldDictionary, int 前行No, int 後行No)
    {
        Dictionary<int, string> newDictionary = new Dictionary<int, string>();
        //何らかの処理
        return newDictionary;
    }
    
[/code]


CC BY-SA 4.0
2020-02-12T13:55:46.127
63005
2020-02-13T02:22:46.423
19705
question
c# .net
前行番号と後行番号を指示して並び替える方法


入れ替えの考え方は以下の記事と類似の考え方で、いったんListにしてから入れ替え、新たにDictionaryを作るやり方で行きます。  
[配列内の順番変更を行うには？](https://ja.stackoverflow.com/q/35963/26370)

以下のようになります。行番号の引数名は srcno, dstno に変えました。

[code]

    static Dictionary<int, string> ChangeOrder(Dictionary<int, string> oldDictionary, int srcno, int dstno)
    {
        // 行番号の範囲チェックが必要ならばこの場所で行う。
    
        // 元のDictionaryの値をkey(行番号)でソートしてリスト化
        List<string> valuelist = new List<string>();
        foreach (var d in oldDictionary.OrderBy((e) => e.Key))
        {
            valuelist.Add(d.Value);
        }
    
        // 行番号1オリジンをリストインデックス0オリジンに変換
        srcno--;
        dstno--;
    
        // リストによる位置の入れ替え
        string temp = valuelist[srcno];
        valuelist.RemoveAt(srcno);
        valuelist.Insert(dstno, temp);
    
        // 新しいDictionaryの作成
        Dictionary<int, string> newDictionary = new Dictionary<int, string>();
        int key = 1;  // keyは1オリジン
        foreach (string s in valuelist)
        {
            newDictionary.Add(key++, s);
        }
        return newDictionary;
    }
    
[/code]


CC BY-SA 4.0
2020-02-12T17:33:35.033
63009
2020-02-12T17:33:35.033
26370
63005
answer


Linqを使って新しいディクショナリを作成する方法です。  
`前行No > 後行No`の場合も想定しています。

使用する場合は下記の留意点にご注意ください

  * ディクショナリのキーを入れ替える処理に複数の三項演算子を使って可読性が低い
  * 連続したキー番号のみを想定している
  * 最初にキー番号で並べ替えている

[code]

    using System;
    using System.Collections.Generic;
    using System.Linq;
    
    namespace ConsoleApp1
    {
        class Program
        {
            static void Main(string[] args)
            {
                Dictionary<int, string> oldDictionary = new Dictionary<int, string>();
                oldDictionary.Add(1, "日本円");
                oldDictionary.Add(2, "アメリカドル");
                oldDictionary.Add(3, "オーストラリアドル");
                oldDictionary.Add(4, "ニュージーランドドル");
    
                foreach (var item in oldDictionary.OrderBy((x) => x.Key))
                {
                    Console.WriteLine(item.Key + "_" + item.Value);
                }
    
                Dictionary<int, string> newDictionary = ChangeOrder(oldDictionary, 2, 4);
                foreach (var item in newDictionary.OrderBy((x) => x.Key))
                {
                    Console.WriteLine(item.Key + "" + item.Value);
                }
                //欲しい結果（2番目のアメリカドルを4番目にする。あとは元の並び順通り）
                //1 日本円
                //2 オーストラリアドル
                //3 ニュージーランドドル
                //4 アメリカドル
    
                newDictionary = ChangeOrder(oldDictionary, 1, 3);
                foreach (var item in newDictionary.OrderBy((x) => x.Key))
                {
                    Console.WriteLine(item.Key + "" + item.Value);
                }
                //欲しい結果（1番目の日本円を3番目にする。あとは元の並び順通り）
                //1 アメリカドル
                //2 オーストラリアドル
                //3 日本円
                //4 ニュージーランドドル
    
                ChangeOrder(oldDictionary, 4, 1).OrderBy(x => x.Key).ToList().ForEach(item =>
                 {
                    Console.WriteLine(item.Key + "" + item.Value);
                });
                //結果（4番目のニュージーランドドルを1番目にする。あとは元の並び順通り）
                //1 ニュージーランドドル
                //2 日本円
                //3 アメリカドル
                //4 オーストラリアドル
    
                Console.ReadLine();
            }
    
            static Dictionary<int, string> ChangeOrder(Dictionary<int, string> oldDictionary, int src, int dst)
            {
                // 行番号の範囲チェックが必要ならばこの場所で行う。
    
                // Dictionaryをコピーして並べ替え
                var dic = new SortedDictionary<int, string>(oldDictionary);
                // 入れ替える並び順を変える係数
                var addition = (src < dst) ? -1 : 1;
                return dic
                        .Select(p => new { k = (p.Key < Math.Min(src, dst) || p.Key > Math.Max(src, dst)) ? p.Key : (p.Key == src) ? dst : p.Key + addition, v = p.Value })
                        .ToDictionary(p => p.k, p => p.v);
            }
        }
    }
    
[/code]


CC BY-SA 4.0
2020-02-13T02:22:46.423
63014
2020-02-13T02:22:46.423
9820
63005
answer