如何将字典中的键交换为值以及将值交换为键

问题描述 投票:0回答:5

伙计们,我想交换字典中的键和值

我的字典是这样的

public static void Main(string[] args)
{
Dictionary<int,int> dic = new Dictionary<int,int>{{1,10}, {2, 20}, {3, 30}};
}

现在我正在打印字典中的值

 foreach (KeyValuePair<int, int> kvp in dic)
{

    Console.WriteLine("Key = {0}, Value = {1}", kvp.Key, kvp.Value);
            Console.ReadKey();
}

在展示中我得到了这个

Key = 1, Value = 10
Key = 2, Value = 20
Key = 3, Value = 30

我想在键和值之间交换值..交换后答案应该是这样的

Key = 10, Value = 1
Key = 20, Value = 2
Key = 30, Value = 3

我做了 lambda 表达式,它改变了,但我需要一些其他方法来做..

c# dictionary swap
5个回答
30
投票

假设值是唯一的,这可以工作:

var dic = new Dictionary<int,int>{{1,10}, {2, 20}, {3, 30}};

var dic2 = dic.ToDictionary(x => x.Value, x=> x.Key);

它实际上不会交换两侧,你会得到一本新字典。


0
投票

这是一个扩展,您可以这样做:

Dictionary<int, int> newDic = oldDic.SwapKeysAndValues();



    /// <summary>
    /// Take a dictionary and make the values the keys and the keys the values
    /// </summary>
    /// <typeparam name="K">The original dictionary key type</typeparam>
    /// <typeparam name="V">The original value type</typeparam>
    /// <param value="dictionary<K, V>"></param>
    /// <returns>Dictionary<V, K></returns>
    public static Dictionary<V, K> SwapKeysAndValues<K, V>(this Dictionary<K, V> original)
    {
        Dictionary<V, K> result = new Dictionary<V, K>();
        foreach (V value in original.Values.Distinct())
        {
            result.Add(value, original.First(x => x.Value.Equals(value)).Key);
        }

        // optional
        //if(original.Count > result.Count)
        //{
        //  throw new Exception("Duplicate value ignored ");
        //}


        return result;
    }

0
投票

我进行了速度测试,发现如果项目数量较多,在不指定容量的情况下创建新字典的速度会变慢。事实上,在 1,000 个项目时,速度慢了约 30%*。此外,如果键和值是相同类型,您可能还希望在相反方向使用相同的 IEqualityComparer。最后,如果您有重复的值,Linq 版本将引发错误。

这里的版本与 Linq 版本基本相同,只是添加了尽可能使用相同的 IEqualityComparer、设置初始容量以及防止潜在的重复错误:

var dic = new Dictionary<int, int>() { { 1, 10 }, { 2, 20 }, { 3, 30 } };
var dic2 = dic.ToDictionarySwapped();

Console.WriteLine(String.Join(",", dic.Select(i => i.Key + ":" + i.Value)));
Console.WriteLine(String.Join(",", dic2.Select(i => i.Key + ":" + i.Value)));

public static Dictionary<V, K> ToDictionarySwapped<K, V>(this Dictionary<K, V> original, bool useSameComparerIfPossible = true)
{
    IEqualityComparer<V> comparer = null;
    if (useSameComparerIfPossible && typeof(K) == typeof(V)) comparer = (IEqualityComparer<V>)original.Comparer;
    var swapped = new Dictionary<V, K>(capacity: original.Count, comparer: comparer);
    foreach (var item in original) swapped[item.Value] = item.Key;
    return swapped;
}
  • 我运行的测试是循环交换包含 1000 个项目的字典 1000 次。在设置容量和未设置容量的情况下重复该测试。设置容量时我的平均时间约为 65 毫秒,未设置容量时约为 95 毫秒。测试在编译为发布模式后运行。

0
投票

原始问题的问题(或者更确切地说,问题之一)是它假设键和值是同一类型,而通用解决方案当然不能做出任何这样的假设。

得票最高的答案的一些问题是:

  1. 没有指定创建地图的容量,所以效率低下

  2. 如果原始地图包含重复值,则失败1

Brain2000 的答案存在的一些问题是:

  1. 在任何非旧版本的 dotnet 下编译时,都会导致与可空性相关的警告。

  2. 它接受

    Dictionary<K,V>
    ,而它应该接受
    IReadOnlyDictionary<K,V>
    。 (参数必须尽可能通用。)

  3. 它返回一个

    Dictionary<K,V>
    ,而它应该返回一个
    IReadOnlyDictionary<K,V>
    。 (函数必须返回不可变的结果。)

  4. 它尝试使用原始映射的比较器,其可取性值得怀疑,并且只有当键和值碰巧属于同一类型时才有效,这种情况不太可能发生,因此不值得考虑中。

  5. 如果原始地图包含重复值,则失败1

已接受答案的一些问题是:

  • 哦,忘了吧。

这是一个解决上述所有问题的函数,并且也有一个正确的名称来说明它的作用。

public static IReadOnlyDictionary<V, K> Transposed<K, V>( this
                    IReadOnlyDictionary<K, V> self )
        where V : notnull
{
    Dictionary<V, K> transposed = new( capacity: self.Count );
    foreach( KeyValuePair<K, V> keyValuePair in self )
        transposed.Add( keyValuePair.Value, keyValuePair.Key );
    return transposed;
}

1 fails to failed:应该发出错误时却没有发出错误;从事无声的失败;愉快地接受你给它的任何垃圾,并通过生产垃圾来破坏你。如果您是脚本语言爱好者,那么这对您来说没有任何意义;忽略,继续前进。


-4
投票

我想你会理解下面的代码:

namespace Swap
{
public class Class1
{
    public SortedDictionary<string, string> names;

    public void BeforeSwaping()
    {
        Console.WriteLine("Before Swapping: ");
        Console.WriteLine();
        names = new SortedDictionary<string, string>();
        names.Add("Sonoo", "srinath");
        names.Add("Perer", "mahesh");
        names.Add("James", "ramesh");
        names.Add("Ratan", "badri");
        names.Add("Irfan", "suresh");
        names.Add("sravan", "current");
        foreach (KeyValuePair<string, string> item in names)
        {

            Console.WriteLine("Key: {0}, Value: {1}", item.Key, item.Value);

        }
        Console.WriteLine();
    }

    public void AfterSwaping()
    {
        Console.WriteLine("After Swapping: ");
        Console.WriteLine();
        var key = names.Keys;
        var val = names.Values;

        string[] arrayKey = new string[key.Count];
        string[] arrayVal = new string[val.Count];
        int i = 0;
        foreach (string s in key)
        {
            arrayKey[i++] = s;
        }
        int j = 0;
        foreach (string s in val)
        {
            arrayVal[j++] = s;
        }
        names.Clear();
        //Console.WriteLine(arrayVal[0] + " " + arrayKey[0]);
        for (int k = 0; k < (arrayKey.Length + arrayVal.Length) / 2; k++)
        {
            names.Add(arrayVal[k], arrayKey[k]);
        }
        foreach (KeyValuePair<string, string> s in names)
        {
            Console.WriteLine("key:"+s.Key + ", "+"value:" + s.Value);
        }
    }
    public static void Main(string[] args)
    {
        Class1 c = new Class1();
        c.BeforeSwaping();
        c.AfterSwaping();
        Console.ReadKey();
    }
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.