# How can a key be renamed in an Association?

Consider an example Association:

assoc = <|"a" -> 1, "b" -> "x", "this_key_is_too_long_to_type" -> {1}|>;


Suppose I want to replace "this_key_is_too_long_to_type" with "c". I can replace it by transforming into Normal land and back into Association land:

Association[
ReplaceAll[Normal[assoc], Rule["this_key_is_too_long_to_type", rhs_] :> Rule["c", rhs]]]


But I have found with Associations that there is usually a compact and efficient way and that this double-transformation is usually a signal that I'm not using it. What's the best way to rename a key?

• Based on the complexity of the answers, I'm going to wager that "... there is usually a compact and efficient way..." is false in this case. – bobthechemist Nov 3 '14 at 22:42
• @bobthechemist, if that's the case, let's use this as an opportunity to request ReplaceKey or something in a future version. – ArgentoSapiens Nov 4 '14 at 0:50
• ...or at least a more general KeyMapAt or AssociationMapAt – Rojo Nov 5 '14 at 11:38
• What property does an Association have that implies that ReplaceAll cannot replace keys? What is the general rule at play here? – Alan Jul 14 '17 at 21:35

There is, of course:

assoc = <|"a" -> 1, "b" -> "x", "this_key_is_too_long_to_type" -> {1}|>;
assoc["c"] = assoc["this_key_is_too_long_to_type"];
assoc["this_key_is_too_long_to_type"] =.
assoc
(* <|"a" -> 1, "b" -> "x", "c" -> {1}|> *)


Not sure if there's an elegant way to do it in one step.

Somewhat similar to the answer of evanb, but without explicit mutations:

keyRename[a_, old_ -> new_] /; KeyExistsQ[a, old] := KeyDrop[old]@Append[a, new -> a[old]]


So that

keyRename[assoc, "this_key_is_too_long_to_type" -> "c"]

(* <|"a" -> 1, "b" -> "x", "c" -> {1}|> *)


It should be noted that this solution doesn't preserve the order of the keys, so if that matters, then solution of evanb is better.

• Hi, Leonid. Your method seems only works for one key. What if I have a bunch to replace. I can't understand why association can not use simply /. For example, assoc/.{c1->d1,c2->d2,...} to replace many keys in a single step. I encountered this kind of occasion many times, quite annoying. – matheorem Nov 2 '15 at 1:17
• @matheorem I think that massive key renaming is not such a common (frequently needed) operation. Using ReplaceAll will be ambiguous - do you want to replace keys or values. Since KeyDrop and Append are constant-time for associations, you can in principle use my keyRename with Fold: Fold[keyRename, assoc, replacements]. Or, if speed is important, do something more clever, all at once, that would be a few times faster. – Leonid Shifrin Nov 2 '15 at 13:45
• @LeonidShifrin, even shorter, along the lines of ArgentoSapiens's O(n): keyReplace[rule_] := KeyMap[Replace[rule]]; keyReplace[{rules__}] := KeyMap[Replace[{rules}]]; /// you'd be surprised how often it's necessary to replace keys programmatically - namespace normalization from multiple sources. – alancalvitti May 7 '17 at 17:20

Here's a way to do it in one line without using Normal first.

KeyMap[If[SameQ[#, "this_key_is_too_long_to_type"], "c", #] &, assoc]


Or:

KeyMap[# /. "this_key_is_too_long_to_type" -> "c" &, assoc]

• The problem with this code is that it is O(n), where n is the number of keys, while it should better be O(1). – Leonid Shifrin Nov 3 '14 at 22:07