在Java中生成字母序列

时间:2012-01-03 10:17:48

标签: java collections sequence guava alphabetical

我正在寻找一种生成字母序列的方法:

A, B, C, ..., Z, AA, AB, AC, ..., ZZ.

任何人都可以建议一种方便的方法。我可以使用哪些数据结构?

我想要获取序列中下一个代码然后重置序列的方法。

16 个答案:

答案 0 :(得分:26)

我将维基百科的Hexavigesimal#Bijective base-26Bijective numeration#Properties of bijective base-k numerals合并来实现:

import static java.lang.Math.*;

private static String getString(int n) {
    char[] buf = new char[(int) floor(log(25 * (n + 1)) / log(26))];
    for (int i = buf.length - 1; i >= 0; i--) {
        n--;
        buf[i] = (char) ('A' + n % 26);
        n /= 26;
    }
    return new String(buf);
}

Wolfram Alpha的帮助下。也许在第一个链接中使用实现会更简单。

答案 1 :(得分:19)

从整数生成字符串的单行递归函数:

static String str(int i) {
    return i < 0 ? "" : str((i / 26) - 1) + (char)(65 + i % 26);
}

使用示例:

public static void main(String[] args) {
    for (int i = 0; i < 27*27; ++i) {
        System.out.println(i + " -> " + str(i));
    }
}

输出:

0 -> A
1 -> B
2 -> C
[...]
24 -> Y
25 -> Z
26 -> AA
27 -> AB
[...]
700 -> ZY
701 -> ZZ
702 -> AAA
703 -> AAB
[...]
727 -> AAZ
728 -> ABA

答案 2 :(得分:7)

我的版本实现了Iterator并维护了一个int计数器。计数器值将转换为相应的字符串:

import com.google.common.collect.AbstractIterator;

class Sequence extends AbstractIterator<String> {
    private int now;
    private static char[] vs;
    static {
        vs = new char['Z' - 'A' + 1];
        for(char i='A'; i<='Z';i++) vs[i - 'A'] = i;
    }

    private StringBuilder alpha(int i){
        assert i > 0;
        char r = vs[--i % vs.length];
        int n = i / vs.length;
        return n == 0 ? new StringBuilder().append(r) : alpha(n).append(r);
    }

    @Override protected String computeNext() {
        return alpha(++now).toString();
    }
}

在迭代器上调用next()以使用它。

Sequence sequence = new Sequence();
for(int i=0;i<100;i++){
  System.out.print(sequence.next() + " ");
}
  

A B C D E F G H I J K L M N O P Q R S T U V W X Y Z AA AB AC AD AE

对于较大序列具有更好性能的实现重用公共前缀:

class SequencePrefix extends AbstractIterator<String> {
    private int now = -1;
    private String prefix = "";
    private static char[] vs;
    static {
        vs = new char['Z' - 'A' + 1];
        for(char i='A'; i<='Z';i++) vs[i - 'A'] = i;
    }

    private String fixPrefix(String prefix){
        if(prefix.length() == 0) return Character.toString(vs[0]);
        int last = prefix.length() - 1;
        char next = (char) (prefix.charAt(last) + 1);
        String sprefix = prefix.substring(0, last);
        return next - vs[0] == vs.length ? 
            fixPrefix(sprefix) + vs[0] : sprefix + next;
    }

    @Override protected String computeNext() {
        if(++now == vs.length) prefix = fixPrefix(prefix);
        now %= vs.length;
        return new StringBuilder().append(prefix).append(vs[now]).toString();
    }
}

如果使用适用于数组的实现重写此基本算法,您将获得更好的性能。 (String.charAt,String.substring和StringBuffer有一些开销。)

答案 3 :(得分:4)

public class SeqGen {
    public static void main(String[] args) {
        //This is the configurable param
        int seqWidth = 3;

        Double charSetSize = 26d;

        // The size of the array will be 26 ^ seqWidth. ie: if 2 chars wide, 26
        // * 26. 3 chars, 26 * 26 * 26
        Double total = Math.pow(charSetSize, (new Integer(seqWidth)).doubleValue());

        StringBuilder[] sbArr = new StringBuilder[total.intValue()];
        // Initializing the Array
        for(int j = 0; j <total; j++){
            sbArr[j] = new StringBuilder();
        }

        char ch = 'A';
        // Iterating over the entire length for the 'char width' number of times.
        // TODO: Can these iterations be reduced?
        for(int k = seqWidth; k >0; k--){
            // Iterating and adding each char to the entire array.        
            for(int l = 1; l <=total; l++){
                sbArr[l-1].append(ch);
                if((l % (Math.pow(charSetSize, k-1d))) == 0){
                    ch++;
                    if(ch > 'Z'){
                        ch = 'A';
                    }
                }
            }
        }

        //Use the stringbuilder array.
        for (StringBuilder builder : sbArr) {
            System.out.println(builder.toString());
        }
    }
}

参考example并根据您的要求进行修改。

答案 4 :(得分:3)

我在下面创建了一个迭代和递归解决方案。您将在这些解决方案后面找到一个示例,其中显示了如何使用迭代器在序列中生成n个项目。另外,为了好玩,我用我的递归解决方案进行了打码。

解决方案

迭代

public static String indexToColumnItr(int index, char[] alphabet) {
    if (index <= 0)
        throw new IndexOutOfBoundsException("index must be a positive number");
    if (index <= alphabet.length)
        return Character.toString(alphabet[index - 1]);
    StringBuffer sb = new StringBuffer();
    while (index > 0) {
        sb.insert(0, alphabet[--index % alphabet.length]);
        index /= alphabet.length;
    }
    return sb.toString();
}

递归

public static String indexToColumnRec(int index, char[] alphabet) {
    if (index <= 0)
        throw new IndexOutOfBoundsException("index must be a positive number");
    if (index <= alphabet.length)
        return Character.toString(alphabet[index - 1]);
    return indexToColumnRec(--index / alphabet.length, alphabet) + alphabet[index % alphabet.length];
}

用法

public static final char[] ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray();

indexToColumnItr(703, ALPHABET); // AAA

实施例

下面的代码生成了以下52大小的序列:

  

[A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, AA, AB, AC, AD, AE, AF, AG, AH, AI, AJ, AK, AL, AM, AN, AO, AP, AQ, AR, AS, AT, AU, AV, AW, AX, AY, AZ]

Main.java

import java.util.Arrays;

public class Main {
    public static void main(String[] args) {
        System.out.println(Arrays.toString(AlphaUtils.generateSequence(52)));
    }
}

AlphaIterator.java

import java.util.Iterator;

public class AlphaIterator implements Iterator<String> {
    private int maxIndex;
    private int index;
    private char[] alphabet;

    public AlphaIterator() {
        this(Integer.MAX_VALUE);
    }

    public AlphaIterator(int maxIndex) {
        this(maxIndex, "ABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray());
    }

    public AlphaIterator(char[] alphabet) {
        this(Integer.MAX_VALUE, alphabet);
    }

    public AlphaIterator(int maxIndex, char[] alphabet) {
        this.maxIndex = maxIndex;
        this.alphabet = alphabet;
        this.index = 1;
    }

    @Override
    public boolean hasNext() {
        return this.index < this.maxIndex;
    }

    @Override
    public String next() {
        return AlphaUtils.indexToColumnItr(this.index++, this.alphabet);
    }
}

AlphaUtils.java

public class AlphaUtils {
    // Iterative
    public static String indexToColumnItr(int index, char[] alphabet) {
        if (index <= 0) throw new IndexOutOfBoundsException("index must be a positive number");
        if (index <= alphabet.length) return Character.toString(alphabet[index - 1]);
        StringBuffer sb = new StringBuffer();
        while (index > 0) {
            sb.insert(0, alphabet[--index % alphabet.length]);
            index /= alphabet.length;
        }
        return sb.toString();
    }

    // Recursive
    public static String indexToColumnRec(int index, char[] alphabet) {
        if (index <= 0) throw new IndexOutOfBoundsException("index must be a positive number");
        if (index <= alphabet.length) return Character.toString(alphabet[index - 1]);
        return indexToColumnRec(--index / alphabet.length, alphabet) + alphabet[index % alphabet.length];
    }

    public static String[] generateSequence(int size) {
        String[] sequence = new String[size];
        int i = 0;
        for (AlphaIterator it = new AlphaIterator(size); it.hasNext();) {
            sequence[i++] = it.next();
        }
        return sequence;
    }
}

Code Golf(89字节): - )

String f(int i,char[]a){int l=a.length;return i<=0?"?":i<=l?""+a[i-1]:f(--i/l,a)+a[i%l];}

答案 5 :(得分:2)

我正在测试,但代码很糟糕......

我制作了我的代码,工作到256 ,但您可以根据需要进行更改。

  public static String IntToLetter(int Int) {
    if (Int<27){
      return Character.toString((char)(Int+96));
    } else {
      if (Int%26==0) {
        return IntToLetter((Int/26)-1)+IntToLetter((Int%26)+1);
      } else {
        return IntToLetter(Int/26)+IntToLetter(Int%26);
      }
    }
  }

已编辑(已修复方法):

  public static String IntToLetter(int Int) {
    if (Int<27){
      return Character.toString((char)(Int+96));
    } else {
      if (Int%26==0) {
        return IntToLetter((Int/26)-1)+IntToLetter(((Int-1)%26+1));
      } else {
        return IntToLetter(Int/26)+IntToLetter(Int%26);
      }
    }
  }

测试我的代码:

  for (int i = 1;i<256;i++) {
    System.out.println("i="+i+" -> "+IntToLetter(i));
  }

结果

    i=1 -> a
    i=2 -> b
    i=3 -> c
    i=4 -> d
    i=5 -> e
    i=6 -> f
    i=7 -> g
    i=8 -> h
    i=9 -> i
    i=10 -> j
    i=11 -> k
    i=12 -> l
    i=13 -> m
    i=14 -> n
    i=15 -> o
    i=16 -> p
    i=17 -> q
    i=18 -> r
    i=19 -> s
    i=20 -> t
    i=21 -> u
    i=22 -> v
    i=23 -> w
    i=24 -> x
    i=25 -> y
    i=26 -> z
    i=27 -> aa
    i=28 -> ab
    i=29 -> ac
    i=30 -> ad
    i=31 -> ae
    i=32 -> af
    i=33 -> ag
    i=34 -> ah
    i=35 -> ai
    i=36 -> aj
    i=37 -> ak
    i=38 -> al
    i=39 -> am
    i=40 -> an
    i=41 -> ao
    i=42 -> ap
    i=43 -> aq
    i=44 -> ar
    i=45 -> as
    i=46 -> at
    i=47 -> au
    i=48 -> av
    i=49 -> aw
    i=50 -> ax
    i=51 -> ay
    i=52 -> az
    i=53 -> ba
    i=54 -> bb
    i=55 -> bc
    i=56 -> bd
    i=57 -> be
    i=58 -> bf
    i=59 -> bg
    i=60 -> bh
    i=61 -> bi
    i=62 -> bj
    i=63 -> bk
    i=64 -> bl
    i=65 -> bm
    i=66 -> bn
    i=67 -> bo
    i=68 -> bp
    i=69 -> bq
    i=70 -> br
    i=71 -> bs
    i=72 -> bt
    i=73 -> bu
    i=74 -> bv
    i=75 -> bw
    i=76 -> bx
    i=77 -> by
    i=78 -> bz
    i=79 -> ca
    i=80 -> cb
    i=81 -> cc
    i=82 -> cd
    i=83 -> ce
    i=84 -> cf
    i=85 -> cg
    i=86 -> ch
    i=87 -> ci
    i=88 -> cj
    i=89 -> ck
    i=90 -> cl
    i=91 -> cm
    i=92 -> cn
    i=93 -> co
    i=94 -> cp
    i=95 -> cq
    i=96 -> cr
    i=97 -> cs
    i=98 -> ct
    i=99 -> cu
    i=100 -> cv
    i=101 -> cw
    i=102 -> cx
    i=103 -> cy
    i=104 -> cz
    i=105 -> da
    i=106 -> db
    i=107 -> dc
    i=108 -> dd
    i=109 -> de
    i=110 -> df
    i=111 -> dg
    i=112 -> dh
    i=113 -> di
    i=114 -> dj
    i=115 -> dk
    i=116 -> dl
    i=117 -> dm
    i=118 -> dn
    i=119 -> do
    i=120 -> dp
    i=121 -> dq
    i=122 -> dr
    i=123 -> ds
    i=124 -> dt
    i=125 -> du
    i=126 -> dv
    i=127 -> dw
    i=128 -> dx
    i=129 -> dy
    i=130 -> dz
    i=131 -> ea
    i=132 -> eb
    i=133 -> ec
    i=134 -> ed
    i=135 -> ee
    i=136 -> ef
    i=137 -> eg
    i=138 -> eh
    i=139 -> ei
    i=140 -> ej
    i=141 -> ek
    i=142 -> el
    i=143 -> em
    i=144 -> en
    i=145 -> eo
    i=146 -> ep
    i=147 -> eq
    i=148 -> er
    i=149 -> es
    i=150 -> et
    i=151 -> eu
    i=152 -> ev
    i=153 -> ew
    i=154 -> ex
    i=155 -> ey
    i=156 -> ez
    i=157 -> fa
    i=158 -> fb
    i=159 -> fc
    i=160 -> fd
    i=161 -> fe
    i=162 -> ff
    i=163 -> fg
    i=164 -> fh
    i=165 -> fi
    i=166 -> fj
    i=167 -> fk
    i=168 -> fl
    i=169 -> fm
    i=170 -> fn
    i=171 -> fo
    i=172 -> fp
    i=173 -> fq
    i=174 -> fr
    i=175 -> fs
    i=176 -> ft
    i=177 -> fu
    i=178 -> fv
    i=179 -> fw
    i=180 -> fx
    i=181 -> fy
    i=182 -> fz
    i=183 -> ga
    i=184 -> gb
    i=185 -> gc
    i=186 -> gd
    i=187 -> ge
    i=188 -> gf
    i=189 -> gg
    i=190 -> gh
    i=191 -> gi
    i=192 -> gj
    i=193 -> gk
    i=194 -> gl
    i=195 -> gm
    i=196 -> gn
    i=197 -> go
    i=198 -> gp
    i=199 -> gq
    i=200 -> gr
    i=201 -> gs
    i=202 -> gt
    i=203 -> gu
    i=204 -> gv
    i=205 -> gw
    i=206 -> gx
    i=207 -> gy
    i=208 -> gz
    i=209 -> ha
    i=210 -> hb
    i=211 -> hc
    i=212 -> hd
    i=213 -> he
    i=214 -> hf
    i=215 -> hg
    i=216 -> hh
    i=217 -> hi
    i=218 -> hj
    i=219 -> hk
    i=220 -> hl
    i=221 -> hm
    i=222 -> hn
    i=223 -> ho
    i=224 -> hp
    i=225 -> hq
    i=226 -> hr
    i=227 -> hs
    i=228 -> ht
    i=229 -> hu
    i=230 -> hv
    i=231 -> hw
    i=232 -> hx
    i=233 -> hy
    i=234 -> hz
    i=235 -> ia
    i=236 -> ib
    i=237 -> ic
    i=238 -> id
    i=239 -> ie
    i=240 -> if
    i=241 -> ig
    i=242 -> ih
    i=243 -> ii
    i=244 -> ij
    i=245 -> ik
    i=246 -> il
    i=247 -> im
    i=248 -> in
    i=249 -> io
    i=250 -> ip
    i=251 -> iq
    i=252 -> ir
    i=253 -> is
    i=254 -> it
    i=255 -> iu

最好的问候

答案 6 :(得分:2)

此方法生成Alpha字符序列

如果使用null调用,则返回A.使用A调用时,返回B.

序列如A,B,C ...... Z,AA,AB,AC ...... AZ,BA,BB,BC .... BZ,CA,CB,CC .. ..CZ,DA ...... ZA,ZB .... ZZ,AAA,AAB,AAC .... AAZ,ABA,ABB ... AZZ,BAA,BAB .... ZZZ

/**
* @param charSeqStr
* @return
*/

public static String getNextAlphaCharSequence(String charSeqStr) {

    String nextCharSeqStr       = null;
    char[] charSeqArr           = null;
    boolean isResetAllChar      = false;
    boolean isResetAfterIndex   = false;
    Integer resetAfterIndex     = 0;

    if (StringUtils.isBlank(charSeqStr)) {
        charSeqArr = new char[] { 'A' };
    } else {
        charSeqArr = charSeqStr.toCharArray();
        Integer charSeqLen = charSeqArr.length;

        for (int index = charSeqLen - 1; index >= 0; index--) {
            char charAtIndex = charSeqArr[index];

            if (Character.getNumericValue(charAtIndex) % 35 == 0) {
                if (index == 0) {
                    charSeqArr = Arrays.copyOf(charSeqArr, charSeqLen + 1);
                    isResetAllChar = true;
                } else {
                    continue;
                }
            } else {
                char nextCharAtIndex = (char) (charAtIndex + 1);
                charSeqArr[index] = nextCharAtIndex;
                if (index + 1 < charSeqLen) {
                    isResetAfterIndex = true;
                    resetAfterIndex = index;
                }
                break;
            }
        }
        charSeqLen = charSeqArr.length;
        if (isResetAllChar) {
            for (int index = 0; index < charSeqLen; index++) {
                charSeqArr[index] = 'A';
            }
        } else if (isResetAfterIndex) {
            for (int index = resetAfterIndex + 1; index < charSeqLen; index++) {
                charSeqArr[index] = 'A';
            }
        }
    }

    nextCharSeqStr = String.valueOf(charSeqArr);
    return nextCharSeqStr;
}

public static void main(String args[]) {
    String nextAlphaSequence = null;
    for (int index = 0; index < 1000; index++) {
        nextAlphaSequence = getNextAlphaCharSequence(nextAlphaSequence);
        System.out.print(nextAlphaSequence + ",");
    }
}

答案 7 :(得分:1)

我建议迭代器返回下一个值。

迭代器需要能够根据内部计数器创建要返回的字符串。对于你的例子,两个计数器就足够了。一个用于字符串中的第一个字符,另一个用于第二个字符。

每个计数器可以对应" ABCDEFGHIJKLMNOPQRSTUVWXYZ"中的索引。当您返回一个字符串时,更新最后一个位置的计数器。如果它“落在边缘”,则将其重置为指向“A”并递增下一个计数器。当该计数器变大时,要么让迭代器指示没有其他元素,要么将其重置为指向“”,具体取决于您的需要。

请注意,通过将第一个位置设为空白,您可以在字符串上使用trim()来删除任何为第一个响应提供“A”的空格。

答案 8 :(得分:1)

有趣的是,还没有人提供基于Java 8的功能解决方案。这是一个使用jOOλ的解决方案,它为字符foldLeft()crossJoin()提供int max = 3; List<String> alphabet = Seq .rangeClosed('A', 'Z') .map(Object::toString) .toList(); Seq.rangeClosed(1, max) .flatMap(length -> Seq.rangeClosed(1, length - 1) .foldLeft(Seq.seq(alphabet), (s, i) -> s.crossJoin(Seq.seq(alphabet)) .map(t -> t.v1 + t.v2))) .forEach(System.out::println); 等功能(免责声明,我为维护jOOλ的公司工作):

{{1}}

这个解决方案并不是很快(e.g. as this one)。为了完整起见,我刚刚添加了它。

答案 9 :(得分:1)

    char ch;
    String str1 = "";
    String str2 = "";

    for (ch = 'A'; ch <= 'Z'; ch++) {
        str1 += ch;
        for (int i = 0; i < 26; i++) {
            char upper = (char) ('A' + i);
            str2 = str2 + ch + upper + " ";

        }
    }

    System.out.println(str1 + ", " + str2);

答案 10 :(得分:0)

这将创建传递值的序列。

/**
 * Method that returns batch names based on passed value
 * @param batchCount
 * @return String[]
 */
public static String[] getBatchNamesForExecutor(int batchCount) {
    // Batch names array
    String[] batchNames = new String[batchCount];

    // Loop from 0 to batchCount required
    for(int index=0; index < batchCount; index++) {
        // Alphabet for current batch name 
        int alphabet = index%26;

        // iteration count happened on all alphabets till now
        int iterations = index/26;

        // initializing array element to blank string
        batchNames[index] = "";

        // Looping over the iterationIndex and creating batch alphabet prefix / prefixes
        for(int iterationIndex = 0; iterationIndex < iterations; iterationIndex+=26){
            batchNames[index] += String.valueOf((char)('A' + (iterations-1) % 26 ));
        }

        // Adding last alphabet in batch name
        batchNames[index] += String.valueOf((char)('A' + alphabet % 26 ));
    }

    return batchNames;
}

public static void main(String[] args) {
    for(String s: getBatchNamesForExecutor(8))  {
        System.err.println(s);
    }
    System.exit(0); 
}

答案 11 :(得分:0)

仅仅因为我喜欢简短的代码......受到Thomas Jung’s answer的启发:

static String asLetters(long value) {
    int codePoint = (int) ('A' + --value % 26);
    long higher = value / 26;
    String letter = new String(Character.toChars(codePoint));
    return higher == 0 ? letter : asLetters(higher).concat(letter);
}

从1→a开始,直至Long.MAX_VALUECRPXNLSKVLJFHG。使用'a'代替'A'获取小写字母。

答案 12 :(得分:0)

采取&#39; A&#39; Z&#39;如26radix。 实施例(C ++)

    vector<string> generateSequenceBySize(int N)
    {
        if(N<1)
            return vector<string>();
        int base = 26;
        vector<string> seqs;
        for(int i=0;i<pow(base,N);i++)
        {
            int value = i;
            string tmp(N,'A');
            for (int j=0;j<N;j++)
            {
                tmp[N-1-j] = 'A'+value%base;
                value = value/base;
            }
            seqs.push_back(tmp);
        }
        return seqs;
    }
    vector<string> generateSequence()
    {
        //http://stackoverflow.com/questions/8710719/generating-an-alphabetic-sequence-in-java
        //A, B, C, ..., Z, AA, AB, AC, ..., ZZ.
        vector<string> seqs;
        for (int i=1;i<=2;i++)
        {
            vector<string> subSeq = generateSequenceBySize(i);
            seqs.insert(seqs.end(),subSeq.begin(),subSeq.end());
        }
        return seqs;
    }

答案 13 :(得分:0)

我不熟悉Java中的函数式编程,但是我想您可以在Haskell中执行与该代码等效的操作:

  

-创建一个列表[“ A” ..“ Z”]

     

uca =地图(:[])['A'..'Z']

     

-两个字符串列表的笛卡尔积,++连接两个字符串

     

cp lst1 lst2 =

    [x ++ y | x <- lst1, y <- lst2]
     

-以下给出了所需的字符串列表

     

uca ++ cp uca uca

答案 14 :(得分:0)

所有这些长答案...以及使用递归的答案...哇。可以用Java在几行中完成而无需递归:

private static String intToValueKey(int value) {
    final StringBuilder sb = new StringBuilder(String.valueOf((char)('A'+(value % 26))));
    while((value = (value/26-1)) >= 0) {
        sb.append((char)('A'+(value % 26)));
    }
    return sb.reverse().toString();
}

然后,您只需在循环中调用递增数值的方法以生成从0到n的序列即可。

for(int i=0; i<800; i++) {
    System.out.println(intToValueKey(i));
}

最后,reverse()只是在乎字母的顺序,如果您只是在寻找唯一的排列,则并不需要。

答案 15 :(得分:-1)

为什么不递归创建序列?

示例(未经测试):

public String createSequenceElement(int index) {
String sequenceElement = "";
int first  = index / 26;
int second = index % 26;
if (first < 1) {
    sequenceElement +=  (char) ('A' + second);
} else {
    sequenceElement +=  createSequenceElement(first) + (char) ('A' + second);
}
return sequenceElement ;
}

public static void main(String[] args) {
    String sequence = "";
    for (int i = 0; i < 100; i++) {
        if (i > 0) {
            sequence += ", ";
        }
        sequence += createSequenceElement(i);

    }
    System.out.println(sequence);
}