遍历一个集合并只打印一条消息,而不是为集合上的每个项目打印一条消息

我正在尝试遍历一个集合以找到一个项目。如果找到该项目,我希望它打印一条消息,如果未找到该项目,则打印另一条消息。到目前为止,它可以工作,但它会为集合中的每个项目打印一条消息,而我只想显示一条消息:如果找到该项目的价格或未找到的消息。我知道这是由于 for 循环而发生的,但我不知道如何让它只显示一次未找到的消息并遍历整个集合。

这是代码:

fun getarticleout(code:String) {

       fun onSuccess(price: Int): String {
           return "Price is $price"
       }

       fun onError(): String {
           return "Article not found"
       }

       for (i in house.articles) {
           if (i.code.equals(code)) {

               val price = calculatePrice(
                   articleType = i.articleType,totalTime = i.totalTime.toInt(),hasCard = !i.hasCard.isnullOrEmpty()
               )

               println(onSuccess(price))

               
               house.articles.remove(i)

           } else {
               println(onError())
           }
       }
}

只是为了澄清:

data class House(val articles: MutableSet<Articles>)
data class Articles(val code: String,var articleType: ArticleType,var totalTime: Calendar,var hasCard:String?=" ")
weiweisenge 回答:遍历一个集合并只打印一条消息,而不是为集合上的每个项目打印一条消息

直接的答案是break 语句,它跳出forwhile 循环。然后,您必须将 onError() 调用移到循环外,以某种方式判断循环是否完成。例如:

   var found = false
   
   for (i in house.articles) {
       if (i.code == code) {
           val price = calculatePrice(
               articleType = i.articleType,totalTime = i.totalTime.toInt(),hasCard = !i.hasCard.isNullOrEmpty())

           println(onSuccess(price))
           house.articles.remove(i)
           found = true
           break
       }
   }
   
   if (!found)
       println(onError())

如果您不需要在两种情况下做任何事情(如相关代码中所示),那么您可以将其简化为return,并避开标志:

   for (i in house.articles) {
       if (i.code == code) {
           val price = calculatePrice(
               articleType = i.articleType,hasCard = !i.hasCard.isNullOrEmpty())

           println(onSuccess(price))
           house.articles.remove(i)
           return
       }
   }
   
   println(onError())

但是,可能有更好的方法不需要手动迭代。 Kotlin 的标准库非常强大,任何时候你发现自己在写一个循环,你应该停下来问问是否有一个库函数可以让它更简单。

特别是,您可以使用 find(),例如:

    val article = house.articles.find{ it.code == code }
    if (article != null) {
        val price = calculatePrice(
            articleType = article.articleType,totalTime = article.totalTime.toInt(),hasCard = !article.hasCard.isNullOrEmpty())

        println(onSuccess(price))
        house.articles.remove(article)
    } else {
        println(onError())
    }

这也使代码更易于阅读。 (请注意,代码现在说明的是它在做什么,而不是如何,这通常是一种改进。)

还有一些更深层次的设计问题值得提出,这可能会导致进一步的简化。例如:

  • 如果 codeArticle 的唯一标识符,另一种选择是使 articlesMap 到相应的 { {1}};检查和删除都将是恒定时间的操作,因此更高效也更简洁。 (当然,这取决于您进行这些查找的频率,以及其他设置或使用 code 的内容。)

  • 或者您可以覆盖 Article 以仅检查代码。然后,您可以使用您要查找的代码创建一个虚拟 articles,并执行一个简单的 Article.equals() 测试(使用集合的 Article 方法)来检查它是否存在。但是,访问和删除集合中的“真实”对象会更困难,因此可能不太合适。

  • in 定义为直接采用 contains 会更简洁吗? (显然这取决于它是否也可以计算其他任何东西的价格。) 它甚至可以是 calculatePrice() 上的方法或扩展函数吗? (这可能取决于价格是概念上文章本身的属性,还是特定于 Article 函数和任何周围代码。)


还值得指出的是,问题中的代码有一个令人讨厌的错误(所有这些更改都可以解决),即它在遍历集合时试图修改它,这很危险!强>

如果幸运的话,您会立即收到ConcurrentModificationException,告诉您到底出了什么问题;如果你不太幸运,它会继续但​​会做一些意想不到的事情,比如跳过一个元素或稍后给出一个明显无关的错误......

这是尽可能避免手动迭代的另一个原因。

(在迭代时删除元素的唯一安全方法是自己管理 Iterator,并使用 that 进行删除。)

本文链接:https://www.f2er.com/811.html

大家都在问