Hadoop wordcount - уменьшить результат метода печати 1 файла до одной строки 1

avatar
Ebet
8 апреля 2018 в 10:51
212
1
1

Я новичок в Hadoop, и я застрял в том, как уменьшить результат 1 файла только до 1 строки. Как этот формат

[filename   v1,v2,v3... v100]

Я попытался напечатать его как ArrayWritable, и результат такой:

a [255]
for[255,24]
to [255,24,10]

и так далее

Но на самом деле я хочу напечатать

[filename 473,255, 30,.... v100]

сгруппировать их все только в 1 строку, а не разделять по ключу.

Ввод представляет собой артикль, например (To Sherlock Holmes she is always THE woman. I have seldom heard him mention her under any other name. In his eyes she eclipses ......)

Формат вывода должен быть «[имя файла v1, v2, v3…, v100]».

  • v1,v2... v100 означает значение в векторе.
  • v1 означает количество слов в слове "the",
  • v2 означает количество слов в слове "быть"

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

public class WordCount implements Tool{
     private final static String[] top100Word = { "the", "be", "to", "of", "and", "a", "in", "that", "have", "i",
                "it", "for", "not", "on", "with", "he", "as", "you", "do", "at", "this", "but", "his", "by", "from", "they",
                "we", "say", "her", "she", "or", "an", "will", "my", "one", "all", "would", "there", "their", "what", "so",
                "up", "out", "if", "about", "who", "get", "which", "go", "me", "when", "make", "can", "like", "time", "no",
                "just", "him", "know", "take", "people", "into", "year", "your", "good", "some", "could", "them", "see",
                "other", "than", "then", "now", "look", "only", "come", "its", "over", "think", "also", "back", "after",
                "use", "two", "how", "our", "work", "first", "well", "way", "even", "new", "want", "because", "any",
                "these", "give", "day", "most", "us" };
     private  static Vector<Integer> vec = new Vector<Integer>(100);
    // private  static ArrayList<IntWritable> list = new ArrayList<IntWritable>();  
     private  static StringBuilder str = new StringBuilder();
     private static String[][] myArray = new String[10][100];


public static class Map extends Mapper<LongWritable, Text, Text, IntWritable> {
    private final static IntWritable one = new IntWritable(1);
    private Text word = new Text();

    public void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
        String line = value.toString();
        StringTokenizer tokenizer = new StringTokenizer(line);
        while (tokenizer.hasMoreTokens()) {
            word.set(tokenizer.nextToken());
            vec.setSize(100);
            context.write(word, one);
        }
    }
} 

public static class Reduce extends Reducer<Text, IntWritable, Text, Text> {

    public void reduce(Text key, Iterable<IntWritable> values, Context context)
            throws IOException, InterruptedException {

int sum=0;
for (IntWritable val : values) {
     sum += val.get();

}



String finalVal = "";
StringBuilder sb = new StringBuilder();
sb.append("");

  for(int i=0;i<top100Word.length;i++){

     Text topValue = new Text(top100Word[i]);
    // vec.add(i,sum);
      if(key.equals(topValue)){
          System.out.println("hi");
          System.out.println("key"+key);
          System.out.println(i);
            vec.add(i,sum);

            //result.set(sum);  //sum= count number
             //  context.write(key, result);
            sb.append(sum);
            String strI = sb.toString();
        myArray[0][i] = strI;
            //list.add(i,new IntWritable(sum));

               if(str.length() > 0)
                  {
                      str.append(",");
                  }
                  str.append(myArray[0][i].toString());





         context.write(key, new Text(str.toString()));

        //  context.write(key, new Text(myArray[0][i]));
            break;
            }
  }





}

}

public int run(String[] args) throws Exception {
       Configuration conf = new Configuration();
       String[] files=new GenericOptionsParser(conf,args).getRemainingArgs();
        Path dst_path = new Path(files[0]);
        Path in_path1 = new Path(files[1]);
        Path in_path2 = new Path(files[2]);
        Path in_path3 = new Path(files[3]);
        FileSystem hdfs = dst_path.getFileSystem(conf);

        if (hdfs.exists(dst_path)){
            hdfs.delete(dst_path, true);
           };


    //Job job = Job.getInstance(conf, "word count");
     Job job = new Job(conf,"word count");
    job.setJarByClass(WordCount.class);

    job.setMapperClass(Map.class);
    job.setReducerClass(Reduce.class);

 // map output types
    job.setMapOutputKeyClass(Text.class);
    job.setMapOutputValueClass(IntWritable.class);
    // reducer output types

    job.setOutputValueClass(Text.class);
    job.setOutputValueClass(Text.class);


    MultipleInputs.addInputPath(job, in_path1, TextInputFormat.class, Map.class);
  //  MultipleInputs.addInputPath(job, in_path2, TextInputFormat.class, Map.class);
   // MultipleInputs.addInputPath(job, in_path3, TextInputFormat.class, Map.class);

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

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

public static void main(String[] args) throws Exception {


      int ecode = ToolRunner.run(new WordCount(), args);

      for(int i=0 ;i<vec.size();i++){

              System.out.println(vec.get(i)+",");
        //  context.write(lastkey,new MyArrayWritable(IntWritable.class, list.toArray(new IntWritable[vec.get(i)])));

      }
      for(int i=0;i<myArray.length;i++){
       if(str.length() > 0)
          {
              str.append(",");
          }
          str.append(myArray[0][i].toString());

      }

      System.out.println(str);


      System.exit(ecode);
     }

@Override
public Configuration getConf() {
    // TODO Auto-generated method stub
    return null;
}

@Override
public void setConf(Configuration arg0) {
    // TODO Auto-generated method stub

}

}
Источник
Nico Haase
8 апреля 2018 в 11:23
0

Можете ли вы уточнить данный вход, ожидаемый результат и где в коде вы застряли?

Ebet
8 апреля 2018 в 11:27
0

Ввод представляет собой статью, например (Для Шерлока Холмса она всегда НАСТОЯЩАЯ женщина. Я редко слышал, чтобы он упоминал ее под каким-либо другим именем. В его глазах она затмевает ......)

Ebet
8 апреля 2018 в 11:28
0

Выходной формат должен быть «[filename v1, v2, v3…, v100]», например, file_1_name 1, 2, 3, 4, …, 100. v1,v2...,v100 означают значение в векторе

Ebet
8 апреля 2018 в 11:28
0

Я застрял в печати, все результаты подсчета слов в 1 строке

Ebet
8 апреля 2018 в 11:29
0

v1 означает количество слов в слове «the», v2 означает количество слов в слове «be».

Ebet
8 апреля 2018 в 11:32
0

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

Nico Haase
8 апреля 2018 в 11:42
1

Пожалуйста, добавляйте все, что имеет отношение к вопросу, а не в раздел комментариев. И проблема сейчас в сборе данных или в их печати? Что вы пытались отладить?

Ebet
8 апреля 2018 в 12:43
0

Я думаю, что проблема заключается в сборе данных, я пытаюсь использовать вектор для хранения данных, чтобы распечатать их только один раз. Но он распечатывает это время. И я не могу отсортировать результат на основе top100Words[]

OneCricketeer
8 апреля 2018 в 13:38
0

Я думаю, вы неправильно понимаете, что одна строка означает использование одного редуктора context.write. Непонятно, почему вы ожидаете, что имя файла будет ключом, но поскольку это не так, а картограф выводит только слово и ключ, вы получаете несколько строк на выходе, по одной на слово.

Ответы (1)

avatar
OneCricketeer
8 апреля 2018 в 14:12
0

Если вы ожидаете, что имя файла будет состоять только из одного ключа, вы не можете просто использовать WordCount в качестве примера кода...

На самом деле подумайте о том, какой вывод вы получаете от преобразователя в редуктор. Например, непонятно, откуда вы берете имя файла. В идеале, если это возможно, это исходит из контекста картографа.

Вывод, генерируемый вашим картографом, в настоящее время разделен на несколько строк без ссылки на то, из какого файла они берутся

(To, 1)
(Sherlock, 1) 
(Holmes, 1)
(she, 1)
(she, 1)

И так далее. И заглавные буквы имеют значение, если вы явно не указываете символы в нижнем регистре.

Мое предложение для вас состоит в том, чтобы выводить некоторую информацию об имени файла, а также суммировать слова строки в преобразователе. Одна строка файла выведет одну запись Reducer, подобную этой

.
(filename, To=1; Sherlock=1; Holmes=1; she=2)

Следующая строка файла создаст аналогичную запись с тем же ключом имени файла и другим текстом значения.

Итак, редюсер увидит один текстовый ключ с итерируемым списком текстовых записей

(filename, ["To=1; Sherlock=1; Holmes=1; she=2", "..."])

Все, что вам нужно сделать, это извлечь текст значения и обобщить его для каждой пары word=count.

И, наконец, проверьте "верхнее слово" в коде преобразователя, а не в редюсере. В противном случае вы тратите впустую ресурсы картографа, которые вам не нужны.

Вот отправная точка для картографа

public static class Map extends Mapper<LongWritable, Text, Text, Text> {
    private static final HashMap<String, Integer> counter = new HashMap<>();
    private Text output = new Text();

    private String mapToString(Map<String, Object> map) {
        StringBuilder sb = new StringBuilder();
        Iterator<Entry<String, Object>> iter = map.entrySet().iterator();
        while (iter.hasNext()) {
            Entry<String, Object> entry = iter.next();
            sb.append(entry.getKey());
            sb.append('=');
            sb.append(entry.getValue().toString());
            if (iter.hasNext()) {
                sb.append(';').append(' ');
            }
        }
        return sb.toString();
    }

    public void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
        // TODO: Get filename
        String line = value.toString();
        StringTokenizer tokenizer = new StringTokenizer(line);
        while (tokenizer.hasMoreTokens()) {
            String token = tokenizer.nextToken();
            if (!counter.containsKey(token)) {
                counter.put(token, 1);
            } else {
                counter.put(token, (Integer) counter.get(token) + 1);
            }
        }
        output.set(mapToString(counter));
        context.write(new Text("filename"), output);
    }
} 

Я оставлю реализацию редуктора на ваше усмотрение. Имейте в виду, что этот код требует от вас extends Reducer<Text, Text, Text, Text>