本文爲轉載,作者:董可倫,鏈接地址:https://dongkelun.com/2018/04/11/sparkNewUV/
前言
本文源自一位羣友的一道美團面試題,解題思路(基於倒排索引)和代碼都是這位大佬(相對於尚處於小白階段的我)寫的,我只是在基於倒排索引的基礎上幫忙想出了最後一步思路,感覺這個解題思路不錯,值得記錄一下。
1、原始數據
2017-01-01 a
2017-01-01 b
2017-01-01 c
2017-01-02 a
2017-01-02 b
2017-01-02 d
2017-01-03 b
2017-01-03 e
2017-01-03 f
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
根據數據可以看出我們要求的結果爲:
2017-01-01 新增三個用戶(a,b,c)
2017-01-02 新增一個用戶(d)
2017-01-03 新增兩個用戶(e,f)
2、解題思路
2.1 對原始數據進行倒排索引
結果如下:
用戶名 | 列一 | 列二 | 列三 |
---|---|---|---|
a | 2017-01-01 | 2017-01-02 | |
b | 2017-01-01 | 2017-01-02 | 2017-01-03 |
c | 2017-01-01 | ||
d | 2017-01-02 | ||
e | 2017-01-03 | ||
f | 2017-01-03 |
2.2 統計列一中每個日期出現的次數
這樣我們只看列一,統計每個日期在列一出現的次數,即爲對應日期新增用戶數。
3、代碼
package com.dkl.leanring.spark.test
import org.apache.spark.sql.SparkSession
object NewUVDemo {
def main(args: Array[String]): Unit = {
val spark = SparkSession.builder().appName("NewUVDemo").master("local").getOrCreate()
val rdd1 = spark.sparkContext.parallelize(
Array(
("2017-01-01", "a"), ("2017-01-01", "b"), ("2017-01-01", "c"),
("2017-01-02", "a"), ("2017-01-02", "b"), ("2017-01-02", "d"),
("2017-01-03", "b"), ("2017-01-03", "e"), ("2017-01-03", "f")))
//倒排
val rdd2 = rdd1.map(kv => (kv._2, kv._1))
//倒排後的key分組
val rdd3 = rdd2.groupByKey()
//取最小時間
val rdd4 = rdd3.map(kv => (kv._2.min, 1))
rdd4.countByKey().foreach(println)
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
結果:
(2017-01-03,2)
(2017-01-02,1)
(2017-01-01,3)
- 1
- 2
- 3
附圖: