具有有序键的 NSDictionary
我有一个 NSDictionary (存储在 plist 中),我基本上将其用作关联数组(字符串作为键和值)。 我想使用键数组作为我的应用程序的一部分,但我希望它们按特定顺序排列(实际上不是我可以编写算法对它们进行排序的顺序)。 我总是可以存储一个单独的键数组,但这似乎有点麻烦,因为我总是必须更新字典的键以及数组的值,并确保它们始终对应。 目前我只使用 [myDictionary allKeys],但显然这会以任意的、无保证的顺序返回它们。 Objective-C 中是否有我缺少的数据结构? 有人对如何更优雅地做到这一点有什么建议吗?
I have an NSDictionary (stored in a plist) that I'm basically using as an associative array (strings as keys and values). I want to use the array of keys as part of my application, but I'd like them to be in a specific order (not really an order that I can write an algorithm to sort them into). I could always store a separate array of the keys, but that seems kind of kludgey because I'd always have to update the keys of the dictionary as well as the values of the array, and make sure they always correspond. Currently I just use [myDictionary allKeys], but obviously this returns them in an arbitrary, non-guaranteed order. Is there a data structure in Objective-C that I'm missing? Does anyone have any suggestions on how to more elegantly do this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
拥有关联的 NSMutableArray 键的解决方案并不是那么糟糕。 它避免了 NSDictionary 的子类化,并且如果您小心地编写访问器,那么保持同步应该不会太难。
The solution of having an associated NSMutableArray of keys isn't so bad. It avoids subclassing NSDictionary, and if you are careful with writing accessors, it shouldn't be too hard to keep synchronised.
我迟到了,但你可能有兴趣调查 CHorderedDictionary。 它是 NSMutableDictionary 的子类,它封装了另一个用于维护键顺序的结构。 (它是 CHDataStructures.framework 的一部分。)我发现它比管理字典和数组更方便分别地。
披露:这是我编写的开源代码。 只是希望它对面临这个问题的其他人有用。
I'm late to the game with an actual answer, but you might be interested to investigate CHOrderedDictionary. It's a subclass of NSMutableDictionary which encapsulates another structure for maintaining key ordering. (It's part of CHDataStructures.framework.) I find it to be more convenient than managing a dictionary and array separately.
Disclosure: This is open-source code which I wrote. Just hoping it may be useful to others facing this problem.
没有这样的内置方法可以让您获取它。 但一个简单的逻辑对你有用。 在准备词典时,您只需在每个键前面添加一些数字文本即可。 就像
现在一样,如果您可以使用 sortingArrayUsingSelector 同时以与您放置的顺序相同的顺序获取所有键。
在UIView中想要显示按键的地方,把前面的3个字符剪掉即可。
There is no such inbuilt method from which you can acquire this. But a simple logic work for you. You can simply add few numeric text in front of each key while you prepare the dictionary. Like
Now if you can use sortingArrayUsingSelector while getting all keys in the same order as you place.
At the place where you want to display keys in UIView, just chop off the front 3 character.
如果你要继承 NSDictionary 的子类,你至少需要实现这些方法:
-计数
-objectForKey:
-keyEnumerator
-removeObjectForKey:
-setObject:forKey:
-copyWithZone:
-mutableCopyWithZone:
-encodeWithCoder:
-initWithCoder:
-countByEnumerateWithState:objects:count:
最简单的方法是创建一个 NSMutableDictionary 的子类,其中包含它自己操作的 NSMutableDictionary 和一个用于存储有序集的 NSMutableArray的钥匙。
如果您永远不会对对象进行编码,则可以想象跳过实现
-encodeWithCoder:
和-initWithCoder:
上述 10 个方法中的所有方法实现都将执行直接通过您的托管字典或有序键数组。
If you're going to subclass NSDictionary you need to implement these methods as a minimum:
-count
-objectForKey:
-keyEnumerator
-removeObjectForKey:
-setObject:forKey:
-copyWithZone:
-mutableCopyWithZone:
-encodeWithCoder:
-initWithCoder:
-countByEnumeratingWithState:objects:count:
The easiest way to do what you want is to make a subclass of NSMutableDictionary that contains its' own NSMutableDictionary that it manipulates and an NSMutableArray to store an ordered set of keys.
If you're never going to encode your objects you could conceivable skip implementing
-encodeWithCoder:
and-initWithCoder:
All of your method implementations in the 10 methods above would then either go directly through your hosted dictionary or your ordered key array.
我的一点补充:按数字键排序(对较小的代码使用简写符号)
My little addition: sorting by numeric key (Using shorthand notations for smaller code)
Quick 'n dirty:
当您需要订购词典(此处称为“myDict”)时,请执行以下操作:
然后,当您需要订购词典时,创建一个索引:
现在, *index 对象将包含正确的顺序。 请注意,此解决方案并不要求所有密钥都必须存在,这是我们正在处理的通常情况......
Quick 'n dirty:
When you need to order your dictionary (herein called “myDict”), do this:
Then, when you need to order your dictionary, create an index:
Now, the *index object will contain the appropriate keys in the correct order. Note that this solution does not require that all the keys necessarily exist, which is the usual situation we're dealing with...
NSDictionary 有序子类的最小实现(基于 https://github.com/nicklockwood/OrderedDictionary )。 请随意扩展以满足您的需求:
Swift 3 和 4
使用
Objective-C
使用
Minimal implementation of an ordered subclass of NSDictionary (based on https://github.com/nicklockwood/OrderedDictionary). Feel free to extend for your needs:
Swift 3 and 4
usage
Objective-C
usage
对于 Swift 3。
请尝试以下方法
For, Swift 3.
Please try out the following approach
我不太喜欢 C++,但我发现自己越来越多地使用的一种解决方案是使用标准模板库中的 Objective-C++ 和
std::map
。 它是一个字典,其键在插入时自动排序。 无论是标量类型还是 Objective-C 对象作为键和值,它都表现得非常好。如果您需要包含数组作为值,只需使用
std::vector
而不是NSArray
。需要注意的是,您可能需要提供自己的
insert_or_assign
函数,除非您可以使用 C++17(请参阅 这个答案)。 另外,您需要typedef
您的类型以防止某些构建错误。 一旦你弄清楚如何使用 std::map、迭代器等,它就会变得非常简单和快速。I don’t like C++ very much, but one solution that I see myself using more and more is to use Objective-C++ and
std::map
from the Standard Template Library. It is a dictionary whose keys are automatically sorted on insertion. It works surprisingly well with either scalar types or Objective-C objects both as keys and as values.If you need to include an array as a value, just use
std::vector
instead ofNSArray
.One caveat is that you might want to provide your own
insert_or_assign
function, unless you can use C++17 (see this answer). Also, you need totypedef
your types to prevent certain build errors. Once you figure out how to usestd::map
, iterators etc., it is pretty straightforward and fast.