我有一个字符串,我想计算所有字母和数字的出现次数,并希望创建一个图形,以便我可以用图形方式查看事件。
例如:
String sentence = "ABC ABC ABC 123"
A (3) * * *
B (3) * * *
C (3) * * *
D
.
.
我的思维方式:
我认为有两种计算角色的方法。我可以使用charAt()
方法或toCharArray()
并循环遍历字符串或数组并计算字母数。
例如:
aCounter = 0;
bCounter = 0;
char ch = sentence.charAt(i);
for (i = 0; i < sentence.length(); ++i) {
if (ch == 'a') {
aCounter++;
}
if (ch == 'b') {
bCounter++;
}
}
但是,这种方法存在多个问题:
aCounter
到zCounter
加0counter
到9counter
我不是在这里要求一个固定的答案,我只是在寻找一些好的方向,因为我被卡住了。
答案 0 :(得分:8)
无需为此制作HashTable/HashMap/HashSet
。
您知道提前跟踪了哪些字符,因此您可以使用数组。
我想计算所有字母和数字的出现次数
创建一个您将跟踪的字符串,然后初始化一个数组。
String sentence = "ABC ABC ABC 123";
//Make a map of all the characters you want to track.
String indexes = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
//Initialize an array to the size of the possible matches.
int[] count = new int[indexes.length()];
//Loop through the sentence looking for matches.
for (int i = 0; i < sentence.length(); i++) {
//This will get the index in the array, if it's a character we are tracking
int index = indexes.indexOf(sentence.charAt(i));
//If it's not a character we are tracking, indexOf returns -1, so skip those.
if (index < 0)
continue;
count[index]++;
}
然后你可以用它打印出来:
for (int i = 0; i < count.length; i++) {
if (count[i] < 1)
continue;
System.out.println(String.format("%s (%d) %s",
indexes.charAt(i),
count[i],
//This little bit of magic creates a string of nul bytes, then replaces it with asterisks.
new String(new char[count[i]]).replace('\0', '*')));
}
如果您对new String(new char[count[i]]).replace('\0', '*'))
位不熟悉,则可以在尝试输出之前使用StringBuilder
构建星号String
。您可以在下面看到 @mike 的示例作为一个很好的示例。
1 (1) *
2 (1) *
3 (1) *
A (3) ***
B (3) ***
C (3) ***
在决定如何解决此问题时,需要考虑以下事项。
char
s的出现次数,而不是String
s?如果你必须修改它来计算String
s,那么使用String indexes
地图技巧也不会对你有效。答案 1 :(得分:2)
以下是一些可以帮助您入门的提示:
不要为每个计数器使用单独的变量。使用数组(或某些集合类型......如果你已经被教过......)。
您可以将字符用作数组索引。
在开始打印任何内容之前累积所有计数。
答案 2 :(得分:2)
您可以使用另一种方法,而不是循环一次计算金额,再循环第二次打印星号,您可以使用另一种方法:
Map<Character,String> results = new HashMap<Character, String>();
然后,每次迭代时,检查地图是否包含角色的数据,如果没有,则初始化它。在伪代码中:
If the map contains data for the key
Obtain the data for the character
append a new asterisk
Else
Create a String with an asterisk
Append an asterisk
Put the String with the character as key
如果你需要数量的星号作为数字,你总是可以获得String
的大小(假设你没有放任何空格)。
作为一项改进,考虑到我与@crush分享的评论,两个调整可以改善逻辑:
StringBuilder
而不是String
:避免不必要的文字创作。TreeMap
代替HashMap
:它会为地图提供正确的顺序,允许对其内容进行分类打印。如果有足够的空间(和知识)来证明其使用的合理性,那就取决于OP增加这些额外的东西。
答案 3 :(得分:2)
这是一种使用StringReader
和Map的OOP方法。我用了TreeMap
将输出排序。
public class StringHistogram
{
public static void main(String[] args) throws IOException
{
Scanner sc = new Scanner(System.in);
System.out.print("Please insert string: ");
String s = sc.nextLine();
sc.close();
System.out.println(s);
StringReader r = new StringReader(s);
Map<Character, Integer> histogram = new TreeMap<Character, Integer>();
int c;
while ((c = r.read()) != -1) {
Integer count = histogram.get((char) c);
if (count == null)
count = 0;
histogram.put((char) c, count + 1);
}
r.close();
for (Entry<Character, Integer> entry : histogram.entrySet())
System.out.println(entry.getKey() + " (" + entry.getValue()
+ ") " + createAsterisk(entry.getValue()));
}
private static String createAsterisk(int number) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < number; i++)
sb.append("*");
return sb.toString();
}
}
答案 4 :(得分:1)
创建一个哈希表并遍历字符串,每次将当前char添加到哈希表
String str = "abc abc abc 123";
Hashtable numbers = new Hashtable();
int size = str.length();
for(int i = 0 ; i< size ; i++)
{
char curr = str.charAt(i);
if(numbers.contains(curr) == false)
{
numbers.put(curr, 1);
}
else
{
numbers.put(curr, ((int)numbers.get(curr)) + 1);
}
}
Enumeration names = numbers.keys();
char c;
while(names.hasMoreElements()) {
c = (char) names.nextElement();
System.out.println(c + ": " +
numbers.get(c));
}
答案 5 :(得分:1)
使用数组存储计数器。您可以直接使用char作为数组索引,因此您不需要复杂的逻辑。
要打印给定数量的星号,for循环是最简单的方法。
答案 6 :(得分:1)
由于您是新手,并且还没有解决方案(每个人都在哪里开始),正确的答案是使用您在课堂上学习的数据结构。
如果您正在学习地图
如果您正在学习数组,那么此线程中有很多例子。暗恋的反应
答案 7 :(得分:0)
将它分为两个方法 - 一个用于给定一个char和一个String来创建一个String“row”,另一个用于为36个字母数字字符中的每一个调用第一个方法。
public static String alphNum = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
public static String count(char c, String str) {
String stringToReturn = Character.toString(c);
for(char ch : str.toCharArray()) {
if (ch == c) {
stringToReturn += " *";
}
}
return stringToReturn;
}
public static void countAndPrintAlphNum(String str) {
String stringToTest = str.toUpperCase();
Set<String> rows = new HashSet<String>();
char[] alphNumArray = alphNum.toCharArray();
for(char c : alphNumArray) {
rows.add(count(c, stringToTest));
}
for(String row : rows) {
System.out.println(row);
}
}
public static void main(String[] args) {
countAndPrintAlphNum("Hi There 123!");
}
注意:如果要确保以字母 - 数字顺序(首先是数字)打印行,请使用TreeSet而不是行的HashSet。
答案 8 :(得分:0)
因为,我们生活在云计算和并行时代。这是另一种方法。
public class DistributedHistogram
{
private static final int PORT = 1337;
private static final String LOOPBACK = "127.0.13.37";
public static final byte[] DATA = new byte[] {(byte) 0xFF, (byte) 0xFF};
public static final byte[] STOP = new byte[] {(byte) 0xDE, (byte) 0xAD};
public static void main(String[] args) throws IOException, InterruptedException
{
ExecutorService se = Executors.newSingleThreadExecutor();
se.submit(new Server(PORT, 16));
System.out.print("Please insert string: ");
Scanner s = new Scanner(System.in);
String input = s.nextLine();
s.close();
System.out.println(input);
ExecutorService ce = Executors.newFixedThreadPool(16);
List<Future<Void>> futures = new ArrayList<Future<Void>>();
for (char c : input.toCharArray())
futures.add(ce.submit(new Client(new Character[]{c}, DATA, LOOPBACK, PORT)));
/* wait for the clients to complete before we send stop to server */
for (Future<Void> f : futures)
{
try
{
@SuppressWarnings ("unused")
Void v = f.get();
}
catch (ExecutionException e)
{
//...
}
}
ce.submit(new StopClient(LOOPBACK, PORT)); // sends stop signal
ce.shutdown();
se.shutdown();
}
}
class Client implements Callable<Void>
{
private final Character[] chars;
private final String ip;
private final int port;
private final byte[] type;
public Client(Character[] chars, byte[] type, String ip, int port)
{
this.chars = chars;
this.type = type;
this.ip = ip;
this.port = port;
}
@Override
public Void call() throws Exception
{
Socket s = new Socket(ip, port);
DataOutputStream out = new DataOutputStream(s.getOutputStream());
for (Character c : chars) {
out.write(type);
out.writeChar(c);
}
out.flush();
out.close();
s.close();
return null;
}
}
class StopClient extends Client {
public StopClient(String ip, int port)
{
super(new Character[]{' '}, DistributedHistogram.STOP, ip, port);
}
}
class Server implements Callable<Void>
{
private final int port;
private ServerSocket ss;
private final ExecutorService e;
private final ConcurrentHistogram ch = new ConcurrentHistogram();
private final AtomicInteger client = new AtomicInteger();
private AtomicBoolean quit = new AtomicBoolean(false);
public Server(int port, int clients)
{
this.port = port;
this.e = Executors.newFixedThreadPool(clients);
}
public ConcurrentHistogram getHistogram() { return ch; }
public void stop()
{
quit.set(true);
e.submit(new Callable<Void>()
{
@Override
public Void call() throws Exception
{
Thread.sleep(250);
ss.close();
return null;
}
});
}
@Override
public Void call() throws Exception
{
ss = new ServerSocket(port);
while (!quit.get() && !ss.isClosed())
{
try
{
e.submit(new ClientHandler(client.getAndIncrement(), ss.accept(), this));
}
catch (SocketException se)
{ continue; }
}
e.shutdown();
System.out.println(ch.toString());
while (!e.isTerminated()) { /* wait */ }
return null;
}
}
class ConcurrentHistogram
{
private final ConcurrentMap<Character, AtomicInteger> histogram = new ConcurrentHashMap<Character, AtomicInteger>();
private static final String HISTOGRAM_CHAR = "*";
public ConcurrentMap<Character, AtomicInteger> getHistogram() { return histogram; }
private String createAsterisk(int number)
{
StringBuilder sb = new StringBuilder();
for (int i = 0; i < number; i++)
sb.append(HISTOGRAM_CHAR);
return sb.toString();
}
@Override
public String toString()
{
StringBuilder sb = new StringBuilder();
List<Entry<Character, AtomicInteger>> data = new ArrayList<Entry<Character, AtomicInteger>>(histogram.entrySet());
Collections.sort(data, new Comparator<Entry<Character, AtomicInteger>>()
{
@Override
public int compare(Entry<Character, AtomicInteger> o1, Entry<Character, AtomicInteger> o2)
{
return o1.getKey().compareTo(o2.getKey());
}
});
for (Entry<Character, AtomicInteger> entry : data)
{
int value = entry.getValue().get();
sb.append(entry.getKey() + " " + String.format("%4s", "(" + value + ")") + " " + createAsterisk(value) + "\n");
}
return sb.toString();
}
public void addChar(Character c)
{
AtomicInteger value = histogram.get(c);
if (value == null)
{
histogram.putIfAbsent(c, new AtomicInteger());
value = histogram.get(c);
}
value.incrementAndGet();
}
}
class ClientHandler implements Callable<Void>
{
@SuppressWarnings ("unused")
private final int client;
private final Socket s;
private final Server server;
public ClientHandler(int client, Socket s, Server server)
{
this.client = client;
this.s = s;
this.server = server;
}
@Override
public Void call() throws Exception
{
DataInputStream in = new DataInputStream(s.getInputStream());
int c;
int i = 0;
byte[] bytes = new byte[2];
while ((c = in.read()) != -1)
{
if (i < 2)
{ bytes[i++] = ((byte) c); }
else if (Arrays.equals(bytes, DistributedHistogram.DATA))
{
i = 0;
char ch = (char) (((c & 0x00FF) << 8) + (in.read() & 0x00FF));
server.getHistogram().addChar(ch);
}
else if (Arrays.equals(bytes, DistributedHistogram.STOP))
{
i = 0;
server.stop();
}
else
{ i = 0; }
}
in.close();
s.close();
return null;
}
}
答案 9 :(得分:0)
这里是最后一个简约的不 OOP答案。有效3线。它有效,因为字符可以解释为整数。
我有点担心不关闭扫描仪。但由于javadoc说System.in
is already open and ready to supply input data
。我假设资源的关闭也由系统处理。
public class MinimalisticHistogram
{
public static void main(String[] args)
{
int[] occurrences = new int[(int) Math.pow(2, 16)]; // 256 KB
for (char c : new Scanner(System.in).nextLine().toCharArray()) occurrences[c]++;
for (int i = 0; i < occurrences.length; i++) if (occurrences[i] != 0) System.out.println(String.format("%c %4s %s", i, "(" + occurrences[i] + ")", new String(new char[occurrences[i]]).replace('\0', '*')));
}
}
答案 10 :(得分:0)
所以我使用了一个双循环来计算字符数。如果某个字符在其中一个数组中匹配,则计数将添加到第三个数组中。
for (int i = 0; i < zinArray.length; i++) { char c = zinArray[i]; for (int j = 0; j < controleArray.length; j++) { char d = controleArray[j]; if (c == d) { letterCount[j]++; break; } } }
答案 11 :(得分:0)
这就是我用StringBuffer
做算法的方法rgb: 255 125 1
argb: 255 125 1 16
输出:
public class StringManipulation { public static void main(String[] args) { int occurrences = 0; int count = 0; int firstLoc = 0; int lastLoc = 0; boolean countedMulti = false; StringBuffer sb = new StringBuffer(); String a = new String("ABC ABC ABC 123"); String lastStrChar = null; char tempChar = 'z'; while (count <= a.length()-1) { for (int scanner = 48; scanner <= 90; scanner++) { if (a.charAt(count) == scanner) { tempChar = (char)scanner; for (int i = 0; i <= a.length() - 1; i++) { if (tempChar == a.charAt(i)) { if (count == 0) { occurrences += 1; sb.append(tempChar); } if (count > 0) { if (a.charAt(count) != a.charAt(count - 1)) { occurrences += 1; } } } if (count == i + 1) { sb.append(tempChar); occurrences = 0; } if ((sb.length() - 1) >= 0) { lastStrChar = sb.substring(sb.length() - 1); firstLoc = sb.indexOf(sb.substring(sb.length() - 1)); lastLoc = sb.length() - 1; if (count>0 && sb.lastIndexOf(lastStrChar,firstLoc) != sb.lastIndexOf(lastStrChar, lastLoc)) { countedMulti = true; //if the index is different for the same character, a duplicate char is found } else { countedMulti = false; } } } if (!countedMulti) { System.out.print(lastStrChar + " appeared " + occurrences + " times\n"); } } } count++; } } }