2016-12-26 2 views
0
 5023971 s 2016-05-22 21:34:48  
     5023971 s 2016-05-22 21:35:57  
     5023971 s 2016-05-22 21:36:35  
     5023971 s 2016-05-22 21:37:42  
     5023971 s 2016-05-22 21:39:41 3 sple 
     5296256 d 2016-03-04 08:05:12  
     5296256 d 2016-03-04 08:05:13  
     5296256 d 2016-03-04 08:05:14 4 sup 
     5324887 d 2016-05-06 10:22:22  
     5324887 d 2016-05-06 10:22:30 2 sup 
     79159 r l 2016-03-13 16:33:59 1 roy 
     1318887 g a 2016-03-15 11:59:09 2 gg 
     1318887 g a 2016-03-21 13:26:13 1 gglrt 
     4821757 y a 2016-05-24 19:46:39 8 hnd 

У нас есть список сотрудников, который содержит идентификатор сотрудника, имя, время, случайное число и действие, выполняемое сотрудником. имя - это один или два токена, но действия всегда с одним токеном. Нам интересно сделать последнее действие, которое сотрудник выполняет с его именем (например: s и sam, d и sup и т. Д.) Код ниже выполняет эту работу, но он извлекает первое действие каждый отдельный сотрудник. Как изменить его для соответствия требованиям?Извлечение последнего действия последнего сотрудника

static StringTokenizer a; 
public static boolean isInteger(String s) { 
try { 
    Integer.parseInt(s); 
} catch(NumberFormatException | NullPointerException e) { 
    return false; 
} 
    return true; 
} 

static boolean first=true; 

    public static void main(String[] args) { 


    BufferedReader br=new BufferedReader(file); 

    String line; 
    String name=""; 
    String tempaction=""; 
    String action=""; 

    while((line=br.readLine())!=null){ 

        int nameLenght=0; 
        String tempName=""; 
        String temp2; 
        String temp3; 
        a=new StringTokenizer(line); 

        if(first){ 
        while(a.hasMoreTokens()){ 
         temp2=a.nextToken(); 
         temp3=temp2.charAt(0)+""; 
         if((temp2).startsWith("2016")) break; 
         if(!isInteger(temp3)){ 
          nameLenght++; 
          tempName=tempName+" "+temp2; 

         } 


        } 
         if(nameLenght<3 && !name.equals(tempName)){ 

          name=tempName; 
          System.out.println(name); 
          first=false; 
         } 
        } 

        action=""; 
        if(!first){ 
         while(a.hasMoreTokens()){ 

         temp2=a.nextToken(); 
         temp3=temp2.charAt(0)+""; 
         if((temp2).startsWith("2016")) break; 
         if(!isInteger(temp3)){ 
          action=action+" "+temp2; 

         }      

        } 

         if(!tempAction.equals(action)){ 
          tempAction=action; 
          System.out.println(action); 
          first=true; 
          } 

         first=true; 
        } 
        } 
    } 
+0

Очень сложно следовать вашей логике, когда ваши переменные имеют бессмысленные имена типа «temp», «temp2',' temp3', 'tempT' и т. Д. Более того, это формат поля фиксированной длины. Не рекомендуется обрабатывать его с помощью токенизатора строк. Логика будет намного проще, если вы захватите поля по их позиции в строке. – RealSkeptic

+0

@RealSkeptic, но имена сотрудников arent фиксированы, они длиннее одного. Поэтому я должен считать длину fitst. если это было 1 или 2, то получите последнее действие. что-то вроде этого. И я сделал несколько изменений для имен варов. temp 2 и temp 3 - это неимпортированные части (идентификаторы, дата и время). – user3049183

+0

В файле, который вы указали, поле имени сотрудника исправлено - это всегда 3 символа, хотя некоторые из них могут быть пробелами. – RealSkeptic

ответ

0

Вот один из способов получения последнего действия для каждого сотрудника (с использованием Java 8 потоков и регулярные выражения)

private static final Pattern LINE_REGEX = Pattern.compile(
     "^\\s*" // space before user id 
     + "[0-9]+" // user id 
     + "\\s+" // space after user id 
     + "(.*?[^\\s])" // user name (group 1) 
     + "\\s+" // space after user name 
     + "([0-9]+-.{14})" // timestamp (group 2) 
     + "\\s+" //space after timestamp 
     + "[0-9]*" // random int 
     + "\\s+" //space after random int 
     + "(.*[^\\s])" // user action (group 3) 
     + "\\s*$" // space after user action 
); 
public static void main(String[] args) throws IOException { 
    try(Stream<String> stream = Files.lines(Paths.get("emplog.txt"))) { 
     Map<String,String> result = stream.map(LINE_REGEX::matcher) 
      // filter out any lines without an Action 
      .filter(Matcher::matches) 
      // group by User 
      .collect(Collectors.groupingBy((Matcher m) -> m.group(1), 
       Collectors.collectingAndThen(
        // compare Timestamp (min for earliest, max for latest) 
        Collectors.maxBy(Comparator.comparing((Matcher m) -> m.group(2))), 
        // extract Action 
        (Optional<Matcher> m) -> m.get().group(3)))); 
     System.out.println(result); 
    } 
} 

Выход:

{s = sple , d = sup, ga = gglrt, ya = hnd, rl = roy}

(Если у каких-либо пользователей нет действий, они не будут указаны.)

+0

(Matcher :: matches) получает недопустимую ссылку для вызова нестатического метода в статическом методе. – user3049183

+0

Я не знаю, почему он не работает над фактическим журналом. Может быть, потому что в фактическом журнале имена завершены? как Дэвид вместо d? или есть какое-то другое объяснение? – user3049183

+0

О, я понял, почему он не работает. в реальном журнале между столбцами есть еще несколько пробелов. Можете ли вы рассказать мне, как изменить свой код, чтобы игнорировать эти пробелы? – user3049183

Смежные вопросы