我正在寻找一种生成字母序列的方法:
A, B, C, ..., Z, AA, AB, AC, ..., ZZ.
任何人都可以建议一种方便的方法。我可以使用哪些数据结构?
我想要获取序列中下一个代码然后重置序列的方法。
答案 0 :(得分:26)
我将维基百科的Hexavigesimal#Bijective base-26和Bijective 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]
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
System.out.println(Arrays.toString(AlphaUtils.generateSequence(52)));
}
}
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);
}
}
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;
}
}
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_VALUE
→CRPXNLSKVLJFHG
。使用'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);
}