Найти значение индекса символа, хранящегося в HashMap
Я пытаюсь напечатать значение индекса соответствующего символа столько раз, сколько оно появится using HashMap
,
Например, скажем, у меня есть String str = "Hello World"
, Программа на данный момент отображает вхождение символов через {d=1, W=1, e=1, r=1, o=2, l=3, H=1}
,
Что я намерен достичь в качестве набора результатов {d=[9], o=[4, 6], r=[7], W=[5], H=[0], l=[2, 3, 8], e=[1]}
где *=[*]
представляет собой key=[indexValue]
,
(Символ пробела не должен учитываться в окончательном наборе результатов.)
import java.util.HashMap;
import java.util.Map;
public class ConcordanceOfStrings {
public static void main(String[] args) {
String str = "Hello World";
//code to remove whitespaces
String newStr = str.replaceAll(" ", "");
Map<Character, Integer> numCount = new HashMap<Character, Integer>(Math.min(newStr.length(), 26));
System.out.println("The count is: ");
for(int i=0; i<newStr.length(); i++){
char charAt = newStr.charAt(i);
if(!numCount.containsKey(charAt)){
numCount.put(charAt, 1);
}
else{
numCount.put(charAt, numCount.get(charAt)+1);
}
}
System.out.println(numCount);
}
}
2 ответа
Вам нужно нечто большее, чем просто карта, вам нужно что-то вроде карты>. Вот пример модификации вашего алгоритма:
Map<Character, List<Integer>> positions = new HashMap<>();
Map<Character, Integer> numCount = new HashMap<Character, Integer>(Math.min(newStr.length(), 26));
for (int i = 0; i < newStr.length(); i++) {
char charAt = newStr.charAt(i);
if (!numCount.containsKey(charAt)) {
numCount.put(charAt, 1);
}
else {
numCount.put(charAt, numCount.get(charAt) + 1);
}
if(!positions.containsKey(charAt)){
List<Integer> cPosition = new LinkedList<>();
cPosition.add(i);
positions.put(charAt, cPosition);
}
else{
List<Integer> cPosition = positions.get(charAt);
cPosition.add(i);
//positions.put(charAt, cPosition); because of references there is no need to do this
}
}
Ты очень близко Прямо сейчас вы сохраняете результат в Map<Character, Integer>
Таким образом, карта каждого символа соответствует количеству его появления в строке.
Чтобы сохранить все индексы, где появляется символ, вам нужно иметь Map<Character, List<Integer>>
: каждый символ будет сопоставлен со списком целых чисел, который будет списком индексов, где появляется этот символ.
В вашем текущем коде вам просто нужно адаптировать логику, которая заполняет карту:
if(!numCount.containsKey(charAt)){
numCount.put(charAt, new ArrayList<>(Arrays.asList(i))); // <-- we store a list containing the first index i
// numCount.put(charAt, 1);
} else{
numCount.get(charAt).add(i); // <-- we add to the existing list the index i
// numCount.put(charAt, numCount.get(charAt)+1);
}
В случае, когда карта не содержит символа, мы инициализируем отображение со списком, содержащим первый индекс i
, Arrays.asList(i)
возвращает список фиксированного размера, поэтому я завернул его в другой ArrayList
,
В случае, когда карта уже содержит символ, нам просто нужно получить текущий список индексов и добавить тот, который мы только что нашли.
Если вы используете Java 8, весь ваш код может быть написан проще с помощью Streams:
Map<Character, List<Integer>> numCount =
IntStream.range(0, str.length())
.filter(i -> str.charAt(i) != ' ')
.boxed()
.collect(Collectors.groupingBy(
i -> str.charAt(i),
Collectors.mapping(v -> v - 1, Collectors.toList())
));