使用带有可为空键的映射?
(Kotlin 新手)我正在编写一个函数来记录两个列表之间的差异,如下所示:
fun logDifferences(booksOne: List<Book>?, booksTwo: List<Book>?, logEntryFactory: LogEntryFactory) {
val booksOneByKey: Map<String?, Book> = booksOne?.associateBy({ it.key }, { it }) ?: mapOf()
val booksTwoByKey: Map<String?, Book> = booksTwo?.associateBy({ it.key }, { it }) ?: mapOf()
val allBookKeysSet: Set<String?> = booksOneByKey.keys.union(booksTwoByKey.keys)
allBookKeysSet.forEach {
val bookOne = booksOneByKey[it]
val bookTwo = booksTwoByKey[it]
if (bookOne != bookTwo) {
bookOne?.let { // log the book) }
bookTwo?.let { // log the book)}
}
}
}
这个想法是,如果 booksOne 或 booksTwo 中的一本书为空,那仍然是我想要的差异捕捉。但正如它所写的,我意识到如果我的映射中的键可以为空,我怎么能查找结果呢?
有没有一种方法可以重构它来记录一个列表具有空对象而另一个列表没有的实例,或者我是否以错误的方式看待这个问题?
(new to Kotlin) I am writing a function to log differences between two Lists, like so:
fun logDifferences(booksOne: List<Book>?, booksTwo: List<Book>?, logEntryFactory: LogEntryFactory) {
val booksOneByKey: Map<String?, Book> = booksOne?.associateBy({ it.key }, { it }) ?: mapOf()
val booksTwoByKey: Map<String?, Book> = booksTwo?.associateBy({ it.key }, { it }) ?: mapOf()
val allBookKeysSet: Set<String?> = booksOneByKey.keys.union(booksTwoByKey.keys)
allBookKeysSet.forEach {
val bookOne = booksOneByKey[it]
val bookTwo = booksTwoByKey[it]
if (bookOne != bookTwo) {
bookOne?.let { // log the book) }
bookTwo?.let { // log the book)}
}
}
}
The idea is that if a book from booksOne or booksTwo is null, that is still a difference that I would like to capture. But as it is written, I am realizing that if a key can be nullable in my map, how could I even look up the result?
Is there a way of refactoring this to log instances where one list has a null object and not the other, or am I looking at this the wrong way?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
即使使用空键,您的代码也可以很好地工作。考虑这个完整的Kotlin程序:
这将打印以下内容:
如您所见,它也将获取NULL书籍
Your code works perfectly fine even with null keys. consider this full kotlin program:
this will print the following:
as you can see it will also take the null book
这不是问题的答案,因为我并不真正了解问题是什么。也许可以使用内置的收集功能来播放:
This is not an answer to the question, as I do not really understand what the issue is. Maybe look and play around with the built-in collection functions:
如果我有正确的话,您有两个具有
id
属性的书籍列表,您想比较这些列表以查找:书中,但仍需要考虑 和书籍,即具有 null ID它出现在两个列表中,但是其中一个ID为无效(即不同的ID)。
我不知道是否有两本具有无效ID的书籍将被视为“两本不同的书籍共享ID”,我想不!
因此,您的问题是该ID是否应该是唯一的,但是它也可以无效,除非您肯定只有一个
id =,否则您不能将其用作密钥。每个列表中的null
。因此,您不能将ID用作查找。真的,您在那里做的不是存储书籍 - 您正在存储ID,而是将其映射到每本书的单书。而且,既然您期望多本书拥有相同的ID(包括NULL),那么对吧?我能想到一些选择。首先,带有不同
id
的简单相同的书籍
,理想情况下,就equals()
而言而言并不相等。不同的数据,对吗?如果是这样,您只需找到仅出现在其中一个列表中的所有book
(如果它们在其他列表中,它们都不匹配):(Yoinking Ivo Becker的设置代码,谢谢!)
这只是使用一些 set set操作 要查找两个列表中不存在的所有项目(相交是两者中的内容,联合就是一切)。
如果您需要将它们分开,以便每个列表都可以记录,则可以执行类似的操作:
如果您出于任何原因无法执行此操作(
book
,具有不同的IDS返回true true for等于
),然后您可以做这样的事情:If I've got this right, you have two lists of Books which have an
id
property, and you want to compare those lists to find:And books with a null ID still need to be considered, i.e. if it only appears in one list (with a null ID), or if it appears in both lists, but the ID is null for one of them (i.e. different IDs).
I don't know if two different books with null IDs would be considered as "two different books sharing an ID", I'll guess no!
So your problem is if that ID is supposed to be unique, but it's also nullable, you can't use it as a key unless you're sure there will only be one with
ID=null
in each list. So you can't use the ID as a lookup. Really what you're doing there isn't storing Books - you're storing IDs, and the single book that maps to each. And since you're expecting multiple books to have the same ID (including null) that's not gonna work, right?There's a couple of options I can think of. First the easy one - the same
Book
with a differentID
is, ideally, not equal as far asequals()
is concerned. Different data, right? If that's the case, you can just find all theBook
s that only appear in one of the lists (i.e. if they are in the other list, they don't match):(yoinking Ivo Becker's setup code, thanks!)
That's just using some set operations to find all the items not present in both lists (the intersect is the stuff that's in both, union is everything).
If you need to keep them separate so you can log per list, you can do something like this:
If you can't do that for whatever reason (
Book
s with different IDs return true forequals
) then you could do something like this: