0

I've got:

String s = "ZpglnRxqenU"

I need to assign a number to each character in the string like:

z-1
p-2
g-3
l-4
n-5
r-6
x-7
q-8
e-9
n-10
u-11

I do not want to count the frequency of characters.

I tried to use HashMap:

 Map<String, Integer> map = new HashMap<>();
        for (int i = 0; i < s.length(); i++) {
          map.put(String.valueOf(s.charAt(i)), i + 1);
 }

But Map a has unique key and I lost first n occurrence

How do I count letters?

Jesse
  • 1,386
  • 3
  • 9
  • 23
IMBABOT
  • 1
  • 2
  • 2
    For what purpose are you trying to do this? A string under the hood is just an array of characters, which is basically what you're asking for. Each character has an index, so for any given character you can just do `index + 1` to get this number. This seems like an [XY problem](https://xyproblem.info/). – Jesse Oct 11 '22 at 20:35
  • Your example output (lowercase) does not match your example input (uppercase). – Basil Bourque Oct 12 '22 at 02:08

3 Answers3

1

Swap the key-value of your map. Use the number for the key, as it will be unique.

Use a NavigableMap to keep them in order.

NavigableMap< Integer , String > = new TreeMap<>() ;

Example code using conventional style.

String input = "ZpglnRxqenU";
int[] codePoints = input.codePoints().toArray();
NavigableMap < Integer, String > numberedCharacters = new TreeMap <>();
for ( int ordinal = 1 ; ordinal <= codePoints.length ; ordinal++ )
{
    numberedCharacters.putIfAbsent(
            ordinal ,
            Character.toString( codePoints[ ordinal - 1 ] )
    );
}

Example code using streams & lambdas. Same effect, not necessarily better in this particular case.

String input = "ZpglnRxqenU";
int[] codePoints = input.codePoints().toArray();
NavigableMap < Integer, String > numberedCharacters =
        IntStream
                .rangeClosed( 1 , codePoints.length )
                .boxed()
                .collect(
                        Collectors.toMap(
                                Function.identity() ,
                                ordinal -> Character.toString( codePoints[ ordinal - 1 ] ) ,
                                ( o1 , o2 ) -> o1 ,
                                TreeMap :: new )
                );

To get all the characters from the map, call values. The resulting Collection object promises to iterate in the order of iteration of the map’s keys.

String recreated = String.join( "" , numberedCharacters.values() );

Dump to console.

System.out.println( "input = " + input );
System.out.println( "numberedCharacters = " + numberedCharacters );
System.out.println( "recreated = " + recreated );

When run.

input = ZpglnRxqenU
numberedCharacters = {1=Z, 2=p, 3=g, 4=l, 5=n, 6=R, 7=x, 8=q, 9=e, 10=n, 11=U}
recreated = ZpglnRxqenU
Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
1

If you want to count the number of characters in a string use s.length();.

If you want to count the number of different characters in a String, you already can with the code you wrote. map.size() will give exactly that, because the map only stores each key once (in your case the 'letters' (they are called char's in java, chars is a diminutive for characters)).

How put() in maps work: The first time you put a key to the map, it is added with the value you give, the second time the value is changed.

UnNamed
  • 21
  • 4
0

Basil's solution should be good enough for what you want but if you strictly want to model like in your example you can have a List<Pair<Character, Integer>> as a storage for your data. There are many libraries offering Pair or Tuplestructures or you could just create your own. Populating your list is a matter of personal taste but in essence you iterate over the characters array, map each character and its index to a new Pair(char, idx) then collect them in a list

Julian
  • 3,678
  • 7
  • 40
  • 72