2014-04-16 2 views
1

나는 짹짹을 가져 와서 데이터베이스에 저장하는 응용 프로그램을 만들고 있습니다. 나는 트윗의 전체 텍스트를위한 열과 트윗의 단어 만 남을 다른 열을 가질 것이다. (나는 나중에 어떤 단어가 가장 많이 사용되었는지 계산할 단어가 필요하다.)그냥 문자열로 문자열을 만드는 더 효율적인 방법

현재 내가하는 일은 6 가지 .replaceAll() 기능 중 일부가 두 번 트리거 될 수있는 기능을 사용하는 것입니다. 예를 들어 replaceAll()을 사용하여 모든 "해시 태그"를 제거하기위한 for 루프가 있습니다.

문제는 내가 몇 분마다 가져 오는 수천 개의 트윗을 편집 할 것이므로 내가하는 일은 너무 효율적이지 않을 것이라고 생각합니다.

내 요구 사항은이 순서 (도 아래로 울부 짖는 소리 코멘트를 작성)에서 무엇 :

  1. 모든 사용자 이름이 모든 해시 태그는
  2. 을 언급 모두 삭제 RT (리트 윗 플래그)
  3. 삭제
  4. 언급 삭제
  5. 모든 줄 바꿈을 공백으로 바꾸십시오.
  6. 모든 공백을 단일 공백으로 바꾸십시오.
  7. 공백을 제외한 모든 특수 문자를 삭제
  8. 여기

짧은과에 Compilable 예입니다 :

public class StringTest { 

    public static void main(String args[]) { 

     String text = "RT @AshStewart09: Vote for Lady Gaga for \"Best Fans\"" 
       + " at iHeart Awards\n" 
       + "\n" 
       + "RT!!\n" 
       + "\n" 
       + "My vote for #FanArmy goes to #LittleMonsters #iHeartAwards" 
       + " htt…"; 

     String[] hashtags = {"#FanArmy", "#LittleMonsters", "#iHeartAwards"}; 
     System.out.println("Before: " + text + "\n"); 

     // Delete all usernames mentioned (may run multiple times) 
     text = text.replaceAll("@AshStewart09", ""); 
     System.out.println("First Phase: " + text + "\n"); 

     // Delete all RT (retweets flags) 
     text = text.replaceAll("RT", ""); 
     System.out.println("Second Phase: " + text + "\n"); 

     // Delete all hashtags mentioned 
     for (String hashtag : hashtags) { 
      text = text.replaceAll(hashtag, ""); 
     } 
     System.out.println("Third Phase: " + text + "\n"); 

     // Replace all break lines with spaces 
     text = text.replaceAll("\n", " "); 
     System.out.println("Fourth Phase: " + text + "\n"); 

     // Replace all double spaces with single spaces 
     text = text.replaceAll(" +", " "); 
     System.out.println("Fifth Phase: " + text + "\n"); 

     // Delete all special characters except spaces 
     text = text.replaceAll("[^a-zA-Z0-9 ]+", "").trim(); 
     System.out.println("Finaly: " + text); 
    } 
} 
+0

교체 코드를 수행하기 전에 문자열을 공백으로 단어로 분할하는 것이 더 효율적입니까? 그런 다음 각 단어에 대해 일치 필터를 개별적으로 실행하십시오. – deanosaur

+0

일부 패턴을 하나의 코드로 결합 할 수 있습니다 (예 :'#FanArmy | #LittleMonsters | #iHeartAwards ") –

+0

@Salauyou 해시 태그를 기본 응용 프로그램에서 어떻게 처리 할 것인지 더 자세히 설명하기 위해 코드를 편집했습니다. –

답변

3

replaceAll에 의존하는 것은 아마도 정규식을 반복적으로 컴파일 할 때 가장 큰 성능 저하 요인 일 것입니다. 모든 것에 regexes를 사용하는 것이 아마도 두 번째로 중요한 문제 일 것입니다. 모든 사용자 이름을 가정

는 다음과 같은 문자가 나열된 사용자 이름 중 하나가 일치 가능성을 건너 뛰는 경우 다음 점검하는 @을 발견한다 때까지 @로, 내가 모든 것을 복사 루프에 의해

// Delete all usernames mentioned (may run multiple times) 
text = text.replaceAll("@AshStewart09", ""); 

을 대체 할 것입니다 시작합니다. 이 조회에는 trie을 사용할 수 있습니다. 더 간단한 방법은 정규 표현식 #\w+HashMap 조회와 함께 replaceAll과 같은 루프가됩니다. 여기

// Delete all RT (retweets flags) 
text = text.replaceAll("RT", ""); 

,

private static final Pattern RT_PATTERN = Pattern.compile("RT"); 

는 확실한 승리. 다음 부분은 모두 비슷하게 처리 할 수 ​​있습니다. 대신

// Delete all special characters except spaces 
text = text.replaceAll("[^a-zA-Z0-9 ]+", "").trim(); 

당신은 구아바의 CharMatcher를 사용할 수 있습니다.방법 removeFrom 정확히 무엇을했는지, collapseFrom 또는 trimAndCollapseFrom 더 좋을 수도 있습니다.

0

당신은 모든 대체하는 하나의 호출에 아무것도로 대체되고있는 모든 것들을 인라인 수 그래서 같은 하나의 호출에 공백으로 대체됩니다 모든 (이 쉽게 것 같은 해시 태그와 사용자 이름을 찾기 위해 정규식을 사용하여) :

text = text.replaceAll("@\w+|#\w+|RT", ""); 
text = text.replaceAll("\n| +", " "); 
text = text.replaceAll("[^a-zA-Z0-9 ]+", "").trim(); 
1

는 지금 question 폐쇄에 따르면, 그것은 모두 두 번째 줄은 세 번째가 너무 \n을 제거처럼 중복 될 것으로 보인다

tweet = tweet.replaceAll("@\\w+|#\\w+|\\bRT\\b", "") 
       .replaceAll("\n", " ") 
       .replaceAll("[^\\p{L}\\p{N} ]+", " ") 
       .replaceAll(" +", " ") 
       .trim(); 

로 요약된다. 첫 번째 줄의 바꾸기를 " "으로 변경해도 대체를 집계 할 수있는 결과는 변경되지 않습니다. 이 특수 문자 부분 소비 할 필요가 없도록

tweet = tweet.replaceAll("@\\w*|#\\w*|\\bRT\\b|[^@#\\p{L}\\p{N} ]+", " ") 
       .replaceAll(" +", " ") 
       .trim(); 

나는, 식사도 혼자 # 또는 @에 사용자 이름과 해시 태그 부분을 변경했습니다. 이것은 [email protected]과 같은 문자열의 corrent 처리에 필요합니다.

성능을 최대화하려면 미리 컴파일 된 패턴이 필요합니다. 나는 또한 Guava의 CharMatcher을 두 번째 부분에 사용하도록 다시 제안합니다. Guava는 거대합니다 (2MB로 추측합니다),하지만 당신은 분명 더 유용한 것들을 발견 할 것입니다. 그래서 결국 얻을 수 있습니다

private static final Pattern PATTERN = 
    Pattern.compile("@\\w*|#\\w*|\\bRT\\b|[^@#\\p{L}\\p{N} ]+"); 
private static final CharMatcher CHAR_MATCHER = CharMacher.is(" "); 

tweet = PATTERN.matcher(tweet).replaceAll(" "); 
tweet = CHAR_MATCHER.trimAndCollapseFrom(tweet, " "); 
+0

두 번째 코드 스 니펫에서 이미 수행 한 작업을 수행 했으므로 한 개의 replaceAll에서 모든 것을 모두 공백으로 만든 다음 모든 여분의 공백을 제거했습니다. 고독한'#'과'@'에 대해서 남겨두면 문제는'[\\ p {L} \\ p {N}] +'에 의해 먹힐까요? 나는 사용자가 확실히'! @ AshStewart09'와 같은 것을 가질 수 있으며, 트위터 자체의 사용자 이름으로 간주되지 않을 것이므로 사용자 이름이 아닐 것입니다. 또한 한 가지 간단한 질문은 C++에서 '정적'작업을 수행하기 때문에 객체를 한 번만 정의 할 수 있습니까? –

+0

나는 당신이 한 일을하고 싶었고,'! @ AshStewart09'를 먼저!와 공백으로 대체했습니다. 이것을 유지하기 위해, 나는 정규 표현식의 두 번째 부분을'@'을 먹게 할 수 없다. 트위터가 어떻게 작동하는지 모르겠다. – maaartinus

+0

예, Java의'static' 필드는 클래스 당 한 번만 존재하며 클래스가로드 될 때 초기화됩니다 (즉, 실제로는 한 번만 사용하거나 클래스를 사용하지 않는 경우 절대 사용하지 마십시오 : D). – maaartinus

관련 문제