2016-11-29 2 views
1

Я изучаю MapReduce, и я хочу прочитать входной файл (предложение по предложению) и написать каждое предложение в выходной файл, только если он не содержит слова «змея».Удалите все предложение, содержащее определенное слово с MapReduce

E.g. Входной файл:

This is my first sentence. This is my first sentence. 
This is my first sentence. 

The snake is an animal. This is the second sentence. This is my third sentence. 

Another sentence. Another sentence with snake. 

Затем выходной файл должен быть:

This is my first sentence. This is my first sentence. 
This is my first sentence. 

This is the second sentence. This is my third sentence. 

Another sentence. 

Чтобы сделать это, я проверяю, в рамках метода map, если предложение (value) содержит слово змею. В случае, если предложение не содержит слова змеи, я пишу это предложение в context.

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

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

This is my first sentence. 
This is my first sentence. 

This is my first sentence. 
This is the second sentence. 
This is my third sentence. 


Another sentence. 

. 

Как я могу написать фразу в новой строке только если это предложение появляется в новой строке во входном тексте? Ниже мой код:

public class RemoveSentence { 

    public static class SentenceMapper extends Mapper<Object, Text, Text, NullWritable>{ 

     private Text removeWord = new Text ("snake"); 

     public void map(Object key, Text value, Context context) throws IOException, InterruptedException { 
      if (!value.toString().contains(removeWord.toString())) { 
       Text currentSentence = new Text(value.toString()+". "); 
       context.write(currentSentence, NullWritable.get()); 
      } 
     } 
    } 


    public static void main(String[] args) throws Exception { 
     Configuration conf = new Configuration(); 
     conf.set("textinputformat.record.delimiter", "."); 

     Job job = Job.getInstance(conf, "remove sentence"); 
     job.setJarByClass(RemoveSentence.class); 

     FileInputFormat.addInputPath(job, new Path(args[0])); 
     FileOutputFormat.setOutputPath(job, new Path(args[1])); 

     job.setMapOutputKeyClass(Text.class); 
     job.setMapOutputValueClass(NullWritable.class); 

     job.setMapperClass(SentenceMapper.class); 
     job.setNumReduceTasks(0); 

     System.exit(job.waitForCompletion(true) ? 0 : 1); 
    } 
} 

This и this other решение говорит, что должно быть достаточно, чтобы установить context.write(word, null);, но в моем случае не работает.

Еще одна проблема связана с conf.set("textinputformat.record.delimiter", ".");. Ну, вот как я определяю разделитель между предложениями, и из-за этого иногда предложение в выходном файле начинается с пробела (например, второго This is my first sentence.). В качестве альтернативы я попытался установить ее так: conf.set("textinputformat.record.delimiter", ". "); (с пробелом после полной остановки), но таким образом приложение Java не записывает в выходной файл все предложения.

ответ

0

Вы очень близки к решению проблемы. Подумайте о том, как работает ваша программа MapReduce. Ваш метод карты принимает каждое отдельное предложение, разделенное символом «.». (по умолчанию это новая строка, как вы знаете) в качестве нового значения, а затем записывает его в файл. Вам нужно свойство, которое отключает запись новых строк после каждого вызова map(). Я не уверен, но я не думаю, что такая собственность существует.

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

This is first sentence. This is second snake. This is last.

Найти слово «змея» и если он найден, удалить все сразу после того, как предыдущий «» к следующему "." Упакуйте новую строку и напишите ее в контекст.

Конечно, если вы можете найти способ отключить новые строки после вызовов map(), то это было бы самым простым.

Надеюсь, это поможет.