количество искровых слов при частичном совпадении - PullRequest
4 голосов
/ 20 сентября 2019

У меня есть такой текстовый файл:

tom
and
jerry
went
to
america
and
england

Я хочу получить частоту каждого слова.

Когда я попробовал следующий код

SparkConf sparkConf = new SparkConf().setMaster("local").setAppName("Word Counter");
JavaSparkContext sparkContext = new JavaSparkContext(sparkConf);
JavaRDD<String> inputFile = sparkContext.textFile("sample.txt");
JavaRDD<String> wordsFromFile = inputFile.flatMap(content -> Arrays.asList(content.split(" ")));
JavaPairRDD countData = wordsFromFile.mapToPair(t -> new Tuple2(t, 1)).reduceByKey((x, y) -> (int) x + (int) y);
countData.saveAsTextFile("CountData");

Я получил следующий вывод

(england,1)
(went,1)
(america,1)
(tom,1)
(to,1)
(jerry,1)
(and,2)

Но мне тоже нужны частичные совпадения.то есть слово to присутствует в слове tom.Таким образом, мое ожидаемое количество слов to составляет 2.Возможен ли этот расчет с использованием spark?

Ответы [ 2 ]

2 голосов
/ 20 сентября 2019

То, что вы хотите сделать, намного сложнее, чем простая группировка по ключу.Одно из возможных решений - начать с уже посчитанных слов в countData и выполнить декартово произведение с самим собой, используя cartesian().Результатом будет СДР с такими элементами, как

((to,1),(tom,1))

. Для каждой такой пары вы проверяете, соответствует ли второй ключ частичному первому (или наоборот), и выводите ключ из первой пары и значение изсекунда.Поскольку декартово произведение симметрично, обработка всех пар не является строго необходимой, только пары, в которых первый ключ лексикографически меньше или равен второму:

((to,1),(tom,1)) -> (to,1) since to <= tom and to partially matches tom
((tom,1),(to,1)) -> (to,0) since tom > to
((to,1),(to,1))  -> (to,1) since to <= to and to (partially) matches to

После этого сопоставления вам нужно только выполнитьуменьшение суммы с помощью reduceByKey, и результат будет именно тем, что вы ищете.

Java не является моим языком выбора, поэтому я не могу дать вам рабочий код, но он должен выглядеть примерно так:

JavaPairRDD partialMatchData = countData
  .cartesian(countData)
  .mapToPair(t -> new Tuple2(t._1._1, partialMatch(t._1._1, t._2._1, t._2._2)))
  .reduceByKey((x, y) -> (int)x + (int)y);

Прототип partialMatch равен (String key1, String key2, int count2) и возвращает count2, если key1 <= key2 иначе 0.

1 голос
/ 20 сентября 2019

вам нужно будет настроить подсчет похожих слов не на строку.правильный способ сделать это: Нечеткое совпадение строк с расстоянием Левенштейна и сходством текста

JavaPairRDD countData = wordsFromFile.mapToPair(t -> new Tuple2(t, 1)).reduceByKey((x, y)(int) x + (int) y);
...