【问题标题】:Scala/Spark efficient partial string matchScala/Spark 高效的部分字符串匹配
【发布时间】:2015-04-21 23:35:02
【问题描述】:

我正在使用 Scala 在 Spark 中编写一个小程序,但遇到了一个问题。我有一个单个单词字符串的列表/RDD 和一个可能包含也可能不包含单个单词列表中的单词的句子列表/RDD。即

val singles = Array("this", "is")
val sentence = Array("this Date", "is there something", "where are something", "this is a string")

我想从单打中选择包含一个或多个单词的句子,结果应该是这样的:

output[(this, Array(this Date, this is a String)),(is, Array(is there something, this is a string))]

我考虑了两种方法,一种是拆分句子并使用 .contains 进行过滤。另一种是将句子拆分并格式化为RDD并使用.join进行RDD交集。我正在查看大约 50 个单词和 500 万个句子,哪种方法会更快?还有其他解决方案吗?你能帮我写代码吗,我的代码似乎没有结果(尽管它编译和运行没有错误)

【问题讨论】:

  • 鉴于每个单词将获得 10 万个句子的平均值,分组可能不是一个真正的选择。 (单词,句子)会是更好的结束格式

标签: string scala apache-spark


【解决方案1】:

您可以创建一组所需的键,在句子中查找键并按键分组。

val singles = Array("this", "is")

val sentences = Array("this Date", 
                      "is there something", 
                      "where are something", 
                      "this is a string")

val rdd = sc.parallelize(sentences) // create RDD

val keys = singles.toSet            // words required as keys.

val result = rdd.flatMap{ sen => 
                    val words = sen.split(" ").toSet; 
                    val common = keys & words;       // intersect
                    common.map(x => (x, sen))        // map as key -> sen
                }
                .groupByKey.mapValues(_.toArray)     // group values for a key
                .collect                             // get rdd contents as array

// result:
// Array((this, Array(this Date, this is a string)),
//       (is,   Array(is there something, this is a string)))

【讨论】:

  • 我应该如何运行子串匹配?想象一下,不是单词列表,而是短语列表: val singles = Array("this book", "is great") 我无法说出这句话!有什么建议吗?
【解决方案2】:

我刚刚尝试解决您的问题,我最终得到了以下代码:

def check(s:String, l: Array[String]): Boolean = {
  var temp:Int = 0
  for (element <- l) {
    if (element.equals(s)) {temp = temp +1}
  }
  var result = false
  if (temp > 0) {result = true}
  result
}
val singles = sc.parallelize(Array("this", "is"))
val sentence = sc.parallelize(Array("this Date", "is there something", "where are something", "this is a string"))
val result = singles.cartesian(sentence)
                    .filter(x => check(x._1,x._2.split(" ")) == true )
                    .groupByKey()
                    .map(x => (x._1,x._2.mkString(", ") ))  // pay attention here(*)
result.foreach(println)

最后一个地图行 (*) 只是因为没有它,我会使用 CompactBuffer 获得一些东西,如下所示:

(is,CompactBuffer(is there something, this is a string))     
(this,CompactBuffer(this Date, this is a string))

使用该地图线(使用 mkString 命令),我会得到更易读的输出,如下所示:

(is,is there something, this is a string)
(this,this Date, this is a string)

希望它能在某种程度上有所帮助。

FF

【讨论】:

  • 500 万个句子的笛卡尔坐标将是一个棘手的问题,但好的答案永远不会少。
  • 你可能是对的......但你可以试一试,看看它是如何工作的......我承认这只是一个“快速”的答案,我可以找到改进它的方法.
  • 其实一点也不差,考虑到它使用的是Spark RDD,它比我只在Master上运行的版本稍慢,但我认为对于更多数据,你的比我的要好得多;此外,如果您考虑一下,笛卡尔可能是最有效的搜索方式。
猜你喜欢
  • 2017-10-11
  • 2021-12-20
  • 2012-09-14
  • 1970-01-01
  • 2012-06-15
  • 2019-10-18
  • 1970-01-01
相关资源
最近更新 更多