2011-09-26 40 views
2

我正在做一個工具,用於優化腳本,現在我想在它的所有名稱壓縮到最低限度。 我得到了功能,開始爲它,但長度超過2後,它在某種程度上錯誤並停止。 有沒有更簡單的方法來做到這一點?我只需要生成從開始一個字符串的模式 - > Z和AA - > AZ BA - > BZ等。短越好唯一ID

public String getToken() { 
    String result = ""; int i = 0; 
    while(i < length){ 
     result = result + charmap.substring(positions[i], positions[i]+1); 
     positions[length]++; 
     if (positions[current] >= charmap.length()){ 
      positions[current] = 0; 
      if (current < 1) { 
       current++;length++; 
      }else{ 
       int i2 = current-1; 
       while(i2 > -1){ 
        positions[i2]++; 
        if(positions[i2] < charmap.length()){ 
         break; 
        }else if(i2 > 0){ 
         positions[i2] = 0; 
        }else{ 
         positions[i2] = 0; 
         length++;current++; 
        } 
        i2--; 

       } 


      } 


     } 
     i++; 
    } 
    return result; 
} 

不同意其他問題!我不只是想增加一個整數,長度增加很多。

回答

1

這裏有一個我用

public class AsciiID { 
    private static final String alphabet= 
        "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; 

    private int currentId; 

    public String nextId() { 
     int id = currentId++; 
     StringBuilder b = new StringBuilder(); 
     do { 
      b.append(alphabet.charAt(id % alphabet.length())); 
     } while((id /=alphabet.length()) != 0); 

     return b.toString(); 
    } 
} 
+1

嘆「好簡單的算法,我們不會爲你做,但這裏有一些提示」.. – Voo

1

我會用一個基座36或基座64(取決於區分大小寫)庫,並與一個整型,而輸出之前運行它,整數轉換爲基36/64號。您可以根據順序來思考,這更容易,輸出值由可信庫處理。

+0

如果我只是想合併字符,我需要一個可信任的庫。而且base64如何製作小型ID。 – Frotty

+0

因爲你正在嘗試做別人已經處理過的事情。根據你的代碼判斷,你遇到了麻煩。那麼爲什麼他人已經做的事情有麻煩? :-基地36就像計數,但你去1,2,3 ... 8,9,a,b,... y,z,10,11..19,1a,1b ...所以你可以做你的邏輯在整數,只是作爲基地輸出36. – corsiKa

+0

MichałŠrajer建議這樣的事情,我怎麼能實現大寫字母? – Frotty

0

您可以搜索經營任何基數的數字圖書館的一些,比如說27,37或更多。然後,您將該數字輸出爲字母數字字符串(如HEX,但帶有a-zA-Z0-9)。

+0

但我沒有找到任何可以幫助我的東西,這就是爲什麼我要求幫助/示例。 – Frotty

0

您可以使用:

Integer.toString(i++, Character.MAX_RADIX) 

這是base36。它不會像Base64那麼大,但是你有一個1行的實現。

+0

雖然這不會在[a-z]中創建字符串表示,但是我不明白爲什麼這是必要的。如果我們使用ASCII輸出不是最有效的表示。 – Voo

+0

我想要什麼,有沒有辦法包括大寫字母? – Frotty

0

那麼讓我們假設我們只能輸出ASCII碼(對於unicode,這個問題變得複雜):快速查看顯示其可打印字符在[32,126]範圍內。所以爲了得到這個問題的最有效率的表示,我們必須在94的基礎上編碼一個給定的整數,並且把32加到任何生成的char上。

你怎麼做到的?查看Sun如何在Integer.toString()中做相應的調整。那麼它可能比必要的更復雜 - 想想你如何將數字轉換爲基數2並適應它。以其最簡單的形式,基本上是一個分區和模的循環。

+0

我可以輸出AZ AZ 0-9 – Frotty

+0

我非常懷疑,因爲我不知道任何僅限於這些字形的字符集。但是,很好 - 所以你必須實現一個基本62(也拋出base64)算法和要麼有一些ifs來決定哪個數字映射到哪個符號,要麼使用字符串和charAt()。這是一個非常簡單的算法,所以不要指望我們爲你做。 – Voo

+0

如果這麼簡單,爲什麼不能在任何地方找到它?所有的base64編碼器都從2或4個字符開始。我想從一個單一的「a」開始。我可以輸出「_」,但那就是它。我必須用不允許其他語言的腳本語言來替換變量名稱。 – Frotty

0

在你的工具,你需要創建一個字典,其中將包含一個唯一的整數ID爲每個唯一的字符串和字符串本身。向字典中添加字符串時,會爲每個新添加的唯一字符串增加給定的ID。一旦字典完成後,您可以使用這樣的事情簡單地轉換ID來String

static final String CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; 
    static final int CHARS_LENGTH = CHARS.length(); 

    public String convert(int id) { 
    StringBuilder sb = new StringBuilder(); 
    do { 
     sb.append(CHARS.charAt(id % CHARS_LENGTH)); 
     id = id/CHARS_LENGTH; 
    } while(id != 0); 
    return sb.toString(); 
    }  
0

這個函數生成的第N個Bijective Number(除零)。這是有史以來最優秀的編碼。 (第零將是空字符串。)

如果有10個可能接受字符,0 - 9,它產生,爲了:

長度的
  • 10串,從 「0」 到「9」
  • 10 * 10長度的字符串,從 「00」 到 「99」
  • 10 * 10 * 10串長度的,從 「000」 到 「999」

該示例使用93個字符,因爲我只是碰巧需要Json。

private static final char[] ALLOWED_CHARS = 
     " !#$%&'()*+,-./:;<=>[email protected][]^_`abcdefghijklmnopqrstuvwxyz{|}~" 
       .toCharArray(); 

private static final AtomicInteger uniqueIdCounter = new AtomicInteger(); 

public static String getToken() { 
    int id = uniqueIdCounter.getAndIncrement(); 
    return toBijectiveNumber(id, ALLOWED_CHARS); 
} 

public static String toBijectiveNumber(int id, char[] allowedChars) { 
    assert id >= 0; 

    StringBuilder sb = new StringBuilder(8); 

    int divisor = 1; 
    int length = 1; 
    while (id >= divisor * allowedChars.length) { 
     divisor *= allowedChars.length; 
     length++; 

     id -= divisor; 
    } 

    for (int i = 0; i < length; i++) { 
     sb.append(allowedChars[(id/divisor) % allowedChars.length]); 
     divisor /= allowedChars.length; 
    } 

    return sb.toString(); 
}