伙计们,我想交换字典中的键和值
我的字典是这样的
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 表达式,它改变了,但我需要一些其他方法来做..
假设值是唯一的,这可以工作:
var dic = new Dictionary<int,int>{{1,10}, {2, 20}, {3, 30}};
var dic2 = dic.ToDictionary(x => x.Value, x=> x.Key);
它实际上不会交换两侧,你会得到一本新字典。
这是一个扩展,您可以这样做:
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;
}
我进行了速度测试,发现如果项目数量较多,在不指定容量的情况下创建新字典的速度会变慢。事实上,在 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;
}
原始问题的问题(或者更确切地说,问题之一)是它假设键和值是同一类型,而通用解决方案当然不能做出任何这样的假设。
得票最高的答案的一些问题是:
没有指定创建地图的容量,所以效率低下
如果原始地图包含重复值,则失败1。
Brain2000 的答案存在的一些问题是:
在任何非旧版本的 dotnet 下编译时,都会导致与可空性相关的警告。
它接受
Dictionary<K,V>
,而它应该接受 IReadOnlyDictionary<K,V>
。 (参数必须尽可能通用。)
它返回一个
Dictionary<K,V>
,而它应该返回一个 IReadOnlyDictionary<K,V>
。 (函数必须返回不可变的结果。)
它尝试使用原始映射的比较器,其可取性值得怀疑,并且只有当键和值碰巧属于同一类型时才有效,这种情况不太可能发生,因此不值得考虑中。
如果原始地图包含重复值,则失败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:应该发出错误时却没有发出错误;从事无声的失败;愉快地接受你给它的任何垃圾,并通过生产垃圾来破坏你。如果您是脚本语言爱好者,那么这对您来说没有任何意义;忽略,继续前进。
我想你会理解下面的代码:
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();
}
}
}