Kotlin Koans 学习笔记 —— Unit 2

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u011133887/article/details/85598967

Kotlin Koans 学习笔记 —— Unit 1

Kotlin Koans第二单元讲的主要是集合在Kotlin中的各种高级操作。

13 介绍

fun Shop.getSetOfCustomers(): Set<Customer> {
    // Return a set containing all the customers of this shop
    return this.customers.toSet()  //将 List 转换成 Set
}

在 Kotlin 中实现了集合类之间转换的各种扩展函数,我们只需要调用 toXXX 就可以简单地将某一个集合转换成另一个!

14 FilterMap 过滤与映射

fun Shop.getCitiesCustomersAreFrom(): Set<City> {
    // Return the set of cities the customers are from
    return this.customers.map {
        it.city
    }.toSet()
}

fun Shop.getCustomersFrom(city: City): List<Customer> {
    // Return a list of the customers who live in the given city
    return this.customers.filter {
        it.city == city
    }
}

fun <T, R> Iterable<T>.map(transform: (T) -> R): List<R> map 映射函数,将一个可d迭代对象按照传入的转换函数变成一个 List 对象。

fun <T> Iterable<T>.filter(predicate: (T) -> Boolean): List<T> filter 过滤函数,将一个可迭代对象根据传入的判断函数进行过滤,并将结果放在一个 List 对象中。

15 AllAnyAndOtherPredicates 判断函数

fun Shop.checkAllCustomersAreFrom(city: City): Boolean {
    // Return true if all customers are from the given city
    return this.customers.all {
        it.isFrom(city)
    }
}

fun Shop.hasCustomerFrom(city: City): Boolean {
    // Return true if there is at least one customer from the given city
    return this.customers.any { it.isFrom(city) }
}

fun Shop.countCustomersFrom(city: City): Int {
    // Return the number of customers from the given city
    return this.customers.count { it.isFrom(city) }
}

fun Shop.findFirstCustomerFrom(city: City): Customer? {
    // Return the first customer who lives in the given city, or null if there is none
    return this.customers.firstOrNull { it.isFrom(city) }
}

全局判断函数:all {(T)->Boolean}返回 boolean 全部满足才返回 true
等同于list.size == list.filter{(T)->Boolean}.size

包含判断函数:any {(T)->Boolean} 返回 boolean 只要满足lambda即返回 true
等同于:list.fliter{(T)->Boolean}.size>0

判断计数函数 count{(T)->Boolean} 返回满足条件的子集数量
等同于list.fliter{(T)->Boolean}.size

判断首项函数:firstOrNull{(T)->Boolean} 返回子集中第一个满足条件的项( T 或者 null)
等同于

var r = list.filter{}
return if (r.size>0) r.get(0) else null

16 FlatMap 平铺映射函数

val Customer.orderedProducts: Set<Product> get() {
    // Return all products this customer has ordered
    //返回用户全部订单中所有的商品种类
    return orders.flatMap {
        it.products
    }.toSet()
}

val Shop.allOrderedProducts: Set<Product> get() {
    // Return all products that were ordered by at least one customer
    //返回商店中全部的至少被一位用户下单过的商品
   customers.flatMap {
        it.orders
    }.flatMap {
        it.products
    }.toSet()

    return customers.flatMap {
        it.orderedProducts
    }.toSet()
}

老规矩先看函数签名 fun <T, R> Iterable<T>.flatMap(transform: (T) -> Iterable<R>): List<R>,该函数是对 Iterable 接口的扩展,flatMap 函数接受一个 transform 函数,这个函数的签名为传入 T 返回 Iterable。

flatMap 看起来与 map 函数很像,最终实现的都是讲一个可序列对象转换成一个 List 对象。不同的是 flatMap 是一对多映射,map 函数是一对一映射。

17 MaxMin 最大最小

fun Shop.getCustomerWithMaximumNumberOfOrders(): Customer? {
    // Return a customer whose order count is the highest among all customers
    return this.customers.maxBy { it.orders.size }
}

fun Customer.getMostExpensiveOrderedProduct(): Product? {
    // Return the most expensive product which has been ordered
    return this.orders.flatMap {
        it.products
    }.maxBy {
        it.price
    }
}

取最大值函数:max()maxBy{} 根据传入的选择器找出集合中最大的成员
fun <T : Comparable<T>> Iterable<T>.max(): T? max 函数签名
fun <T, R : Comparable<R>> Iterable<T>.maxBy(selector: (T) -> R): T? maxBy 函数签名

18 排序函数

fun Shop.getCustomersSortedByNumberOfOrders(): List<Customer> {
    // Return a list of customers, sorted by the ascending number of orders they made
    return this.customers.sortedBy {
        it.orders.size
    }
}

排序函数:sortedBy{} 根据传入的选择器升序排列

19 求和函数

//三种求和实现方法
fun Customer.getTotalOrderPrice(): Double {
    // Return the sum of prices of all products that a customer has ordered.
    // Note: a customer may order the same product for several times.
    //使用求和函数
    orders.flatMap {
        it.products
    }.sumByDouble {
        it.price
    }
	//使用fold函数
    orders.flatMap { it.products }.fold(0.0,{acc, product ->
            acc+product.price
    })
    //使用 forEach函数
    var result = 0.0
    orders.flatMap { it.products }.forEach {
        result+=it.price
    }
    return  result
}

求和函数:sum()返回Int、 sumBy{}返回 Int、 sumByDouble{} 返回 Double

20 分组函数

fun Shop.groupCustomersByCity(): Map<City, List<Customer>> {
    // Return a map of the customers living in each city
    //不使用groupBy函数的写法
    val map = mutableMapOf<City,List<Customer>>()
    val citys = this.customers.map {
        it.city
    }.toSet().map {
        map.put(it, this.getCustomersFrom(it))
    }

    return this.customers.groupBy { it.city }
}

分组函数 groupBy{} 按照传入的选择器将集合对象分组返回Map<K, List<T>>

21 Partition 划分函数

fun Shop.getCustomersWithMoreUndeliveredOrdersThanDelivered(): Set<Customer> {
    // Return customers who have more undelivered orders than delivered
   return  this.customers.filter {
       val (delivered,undelivered) = it.orders.partition { it.isDelivered }
       undelivered.size>delivered.size
   }.toSet()
}

fun <T> Iterable<T>.partition(predicate: (T) -> Boolean): Pair<List<T>, List<T>> 根据传入的判断函数,将可迭代对象划分为满足条件与不满足条件两个 List 对象,然后放入 Pair 对象中,其中 first 为满足判断函数,second 为不满足判断函数。

22 Fold 折叠函数

fun Shop.getSetOfProductsOrderedByEachCustomer(): Set<Product> {
    // Return the set of products that were ordered by each of the customers
    //找到商店中每一个用户都下单的商品
    allOrderedProducts.filter { p ->
        customers.all {
            it.orders.flatMap {
                it.products
            }.any {
                it == p
            }
        }
    }.toSet()

    return customers.fold(allOrderedProducts, { orderedByAll, customer ->
        //第一次调用该函数时传入值为fold函数的第一个参数 全部被下单的产品集合
        orderedByAll.intersect( //交集运算
                customer.orders.flatMap {
                    it.products
                }.toSet() //传入的用户的全部产品的集合
        )
    })
}

老规矩看源码:

public inline fun <T, R> Iterable<T>.fold(initial: R, operation: (acc: R, T) -> R): R {
    var accumulator = initial
    for (element in this) accumulator = operation(accumulator, element)
    return accumulator
}

这个函数还是很好理解的,fold 函数是可迭代对象的扩展函数,有两个参数,第一个参数为初始值,第二个参数为操作函数。操作函数接受两个参数,第一个函数为初始值,第二个参数是可迭代对象的子元素,操作函数的返回值为初始值的类型。

23 CompoundTask

fun Shop.getCustomersWhoOrderedProduct(product: Product): Set<Customer> {
    // Return the set of customers who ordered the specified product
    //根据传入的商品返回全部订购该商品的用户
    return customers.filter {
        it.orders.flatMap {
            it.products
        }.any {
            it==product
        }
    }.toSet()
}

fun Customer.getMostExpensiveDeliveredProduct(): Product? {
    // Return the most expensive product among all delivered products
    //返回已经完成交付的最贵的商品
    // (use the Order.isDelivered flag)
    return this.orders.filter {
        it.isDelivered
    }.flatMap {
        it.products
    }.maxBy {
        it.price
    }
}

fun Shop.getNumberOfTimesProductWasOrdered(product: Product): Int {
    // Return the number of times the given product was ordered.
    // Note: a customer may order the same product for several times.
    //根据传入的商品返回该商品被订购的次数,注意一个客户可能订购同一个商品数次
    return customers.flatMap {
        it.orders
    }.flatMap {
        it.products
    }.count {
        it==product
    }
}

24 集合的扩展

fun doSomethingStrangeWithCollection(collection: Collection<String>): Collection<String>? {
    val groupsByLength = collection.groupBy { s -> s.length }
    return groupsByLength.values.maxBy { group -> group.size }
}

这个任务的要求是仿照 _24_JavaCode.doSomethingStrangeWithCollection 这个函数,用 kotlin 书写完成相同的功能。

public Collection<String> doSomethingStrangeWithCollection(Collection<String> collection) {
    Map<Integer, List<String>> groupsByLength = Maps.newHashMap();
    for (String s : collection) {
        List<String> strings = groupsByLength.get(s.length());
        if (strings == null) {
            strings = Lists.newArrayList();
            groupsByLength.put(s.length(), strings);
        }
        strings.add(s);
    }
    int maximumSizeOfGroup = 0;
    for (List<String> group : groupsByLength.values()) {
        if (group.size() > maximumSizeOfGroup) {
            maximumSizeOfGroup = group.size();
        }
    }
    for (List<String> group : groupsByLength.values()) {
        if (group.size() == maximumSizeOfGroup) {
            return group;
        }
    }
    return null;
}

原 Java 函数实现的功能是,将传入的 Collection<String> 根据字符串的长度分组,然后返回数量最多的那个。在 Kotlin 中只需要适当使用 groupBy{} 函数与 maxBy{} 就可以完成这个功能.

猜你喜欢

转载自blog.csdn.net/u011133887/article/details/85598967