Kotlin:从列表中的嵌套集中查找计数(更实用的方法)
Kotlin: Find Count from Nested set in List (more functional approach)
下面的函数创建一个地图,获取乘客数量> minTrips。该代码完全可以正常工作。请看下面
fun List<Trip>.filter(minTrips : Int): Set<Passenger> {
var passengerMap: HashMap<Passenger, Int> = HashMap()
this.forEach { it: Trip ->
it.passengers.forEach { it: Passenger ->
var count: Int? = passengerMap.get(it)
if (count == null) {
count = 1
passengerMap.put(it, count)
} else {
count += 1
passengerMap.put(it, count)
}
}
}
val filteredMinTrips: Map<Passenger, Int> = passengerMap.filterValues { it >= minTrips }
println (" Filter Results = ${filteredMinTrips}")
return filteredMinTrips.keys
}
尽管这是用 Kotlin 编写的,但代码似乎首先是用 Java 编写的,然后转换为 Kotlin。如果它真的是用 Kotlin 编写的,我相信这不会有这么多行代码。如何减少代码行数?什么是解决这个问题的更有效的方法?我可以使用哪些函数或函数直接在 Passengers are > minTrips 的位置提取 Passengers Set?这是太多的代码,看起来很疯狂。任何指针在这里都会有所帮助。
您基本上想计算每位乘客的行程,因此您可以将所有乘客放在一个列表中,然后按他们分组,然后计算每组中的出现次数:
fun List<Trip>.usualPassengers(minTrips : Int) = // 1
flatMap(Trip::passengers) // 2
.groupingBy { it } // 3
.eachCount() // 4
.filterValues { it >= minTrips } // 5
.keys // 6
解释:
- return类型
Set<Passenger>
可以推断
this
可以省略,[p1, p2, p1, p5, ...]
形式的列表是 returned
- 创建了一个Grouping,看起来像这样
[p1=[p1, p1], p2=[p2], ...]]
- 将计算每组中出现的次数:
[p1=2, p2=1, ...]
- 所有小于
minTrips
的元素将被过滤掉
- 剩下的所有键都将 returned
[p1, p2, ...]
p1...pn
是 Passenger 实例
实现此目的的一种方法是利用 Kotlin 的平面图和分组调用。通过创建所有行程中所有乘客的列表,您可以对他们进行分组、计数,以及 return 超过一定数量的乘客。
假设您有这样的数据 类(仅基本细节):
data class Passenger(val id: Int)
data class Trip(val passengers: List<Passenger>)
我能写这个:
fun List<Trip>.frequentPassengers(minTrips: Int): Set<Passenger> =
this
.flatMap { it.passengers }
.groupingBy { it }
.eachCount()
.filterValues { it >= minTrips }
.keys
这很好,因为它是单个表达式。通过它,我们查看每个 Trip
并提取其所有 Passengers
。如果我们刚刚在这里完成 map
,我们将得到 List<List<Passenger>>
,但我们想要一个 List<Passenger>
,所以我们平面图来实现它。接下来,我们 groupBy
Passenger
对象本身,并在 returned 对象上调用 eachCount()
,给我们一个 Map<Passenger, Int>
。最后,我们将地图过滤掉我们感兴趣的乘客,以及 return 键集。
请注意,我重命名了您的函数,List
上已经有一个 filter
,尽管签名不同,但我发现它很混乱。
下面的函数创建一个地图,获取乘客数量> minTrips。该代码完全可以正常工作。请看下面
fun List<Trip>.filter(minTrips : Int): Set<Passenger> {
var passengerMap: HashMap<Passenger, Int> = HashMap()
this.forEach { it: Trip ->
it.passengers.forEach { it: Passenger ->
var count: Int? = passengerMap.get(it)
if (count == null) {
count = 1
passengerMap.put(it, count)
} else {
count += 1
passengerMap.put(it, count)
}
}
}
val filteredMinTrips: Map<Passenger, Int> = passengerMap.filterValues { it >= minTrips }
println (" Filter Results = ${filteredMinTrips}")
return filteredMinTrips.keys
}
尽管这是用 Kotlin 编写的,但代码似乎首先是用 Java 编写的,然后转换为 Kotlin。如果它真的是用 Kotlin 编写的,我相信这不会有这么多行代码。如何减少代码行数?什么是解决这个问题的更有效的方法?我可以使用哪些函数或函数直接在 Passengers are > minTrips 的位置提取 Passengers Set?这是太多的代码,看起来很疯狂。任何指针在这里都会有所帮助。
您基本上想计算每位乘客的行程,因此您可以将所有乘客放在一个列表中,然后按他们分组,然后计算每组中的出现次数:
fun List<Trip>.usualPassengers(minTrips : Int) = // 1
flatMap(Trip::passengers) // 2
.groupingBy { it } // 3
.eachCount() // 4
.filterValues { it >= minTrips } // 5
.keys // 6
解释:
- return类型
Set<Passenger>
可以推断 this
可以省略,[p1, p2, p1, p5, ...]
形式的列表是 returned- 创建了一个Grouping,看起来像这样
[p1=[p1, p1], p2=[p2], ...]]
- 将计算每组中出现的次数:
[p1=2, p2=1, ...]
- 所有小于
minTrips
的元素将被过滤掉 - 剩下的所有键都将 returned
[p1, p2, ...]
p1...pn
是 Passenger 实例
实现此目的的一种方法是利用 Kotlin 的平面图和分组调用。通过创建所有行程中所有乘客的列表,您可以对他们进行分组、计数,以及 return 超过一定数量的乘客。
假设您有这样的数据 类(仅基本细节):
data class Passenger(val id: Int)
data class Trip(val passengers: List<Passenger>)
我能写这个:
fun List<Trip>.frequentPassengers(minTrips: Int): Set<Passenger> =
this
.flatMap { it.passengers }
.groupingBy { it }
.eachCount()
.filterValues { it >= minTrips }
.keys
这很好,因为它是单个表达式。通过它,我们查看每个 Trip
并提取其所有 Passengers
。如果我们刚刚在这里完成 map
,我们将得到 List<List<Passenger>>
,但我们想要一个 List<Passenger>
,所以我们平面图来实现它。接下来,我们 groupBy
Passenger
对象本身,并在 returned 对象上调用 eachCount()
,给我们一个 Map<Passenger, Int>
。最后,我们将地图过滤掉我们感兴趣的乘客,以及 return 键集。
请注意,我重命名了您的函数,List
上已经有一个 filter
,尽管签名不同,但我发现它很混乱。