У меня длинный текстовый файл, и мне нужно перемешать все слова, длина которых превышает 4 буквы, но другие слова должны оставаться на том же месте. Это без с использованием модуля Коллекции.
Мне удается перетасовать все строки в массиве, но я не могу понять, как перетасовать только часть.
public static String[] getScramble(String text) {
Random rgen=new Random();
String[] textArray=text.split(" ");
for(int i=0;i<textArray.length;i++){
int randPos=rgen.nextInt(textArray.length);
String temp=textArray[i];
if (textArray[i].length()>4){
textArray[i]=textArray[randPos];
textArray[randPos]=temp;
}else{
textArray[i]=textArray[i];
}
}
return textArray;
Спасибо!




Вы меняете местами только два слова, если оба длиннее 4 символов, в противном случае вы сохраняете их в исходной позиции:
for(int i = 0; i < textArray.length; i++) {
int randPos = rgen.nextInt(textArray.length);
if (textArray[i].length() > 4 && textArray[randPos].length() > 4){
String temp = textArray[i];
textArray[i]=textArray[randPos];
textArray[randPos]=temp;
}
}
Обновлено: если количество длинных слов очень мало по сравнению с количеством коротких слов, этот цикл может вести себя плохо (поскольку он не сможет поменять местами большую часть длинных слов), поэтому вы можете улучшить его следующим образом:
for(int i=0;i<textArray.length;i++){
if (textArray[i].length() > 4) {
// find a long word to swap textArray[i] with
int randPos=rgen.nextInt(textArray.length);
while (textArray[randPos].length() <= 4){
randPos=rgen.nextInt(textArray.length);
}
// swap the two long words
String temp=textArray[i];
textArray[i]=textArray[randPos];
textArray[randPos]=temp;
}
}
При генерации случайной позиции для слова, длина которого превышает 4 символа, вы проверяете, есть ли в новой позиции также слово, содержащее более 4 символов. Если нет, вы продолжаете генерировать новую случайную позицию, пока не найдете подходящую.
public static String[] getScramble(String text) {
Random rgen = new Random();
String[] textArray = text.split(" ");
for (int i = 0; i < textArray.length; i++) {
if ( textArray[i].length() > 4) {
String temp = textArray[i];
int randPos = rgen.nextInt(textArray.length);
while( textArray[randPos].length() <= 4 ){
randPos = rgen.nextInt(textArray.length);
}
textArray[i] = textArray[randPos];
textArray[randPos] = temp;
}
}
return textArray;
}
Ситуация, которая может возникнуть, если у вас есть только одно слово, состоящее из более чем 4 символов, что означает, что бессмысленно даже пытаться рандомизировать их, и вы можете потратить много времени на генерацию случайных позиций безрезультатно. Чтобы оптимизировать это, вы можете сначала проверить, меньше ли у вас двух длинных слов, и если да, то вам ничего не нужно делать.
int longWordCount = 0;
for (int i = 0; i < textArray.length; i++) {
if ( textArray[i].length() > 4 )
longWordCount++;
if ( longWordCount == 2 )
break;
}
if ( longWordCount > 1 ) {
for (int i = 0; i < textArray.length; i++) {
if (textArray[i].length() > 4) {
String temp = textArray[i];
int randPos = rgen.nextInt(textArray.length);
while (textArray[randPos].length() <= 4) {
randPos = rgen.nextInt(textArray.length);
}
textArray[i] = textArray[randPos];
textArray[randPos] = temp;
}
}
}
Вот версия, которая адаптирует Алгоритм Дюрстенфельда. Обратите внимание, что ThreadLocalRandom предпочтительнее Random.
public static String[] getScramble(String text) {
ThreadLocalRandom rgen = ThreadLocalRandom.current();
String[] textArray = text.split(" ");
int[] indices = IntStream.range(0, textArray.length)
.filter(i -> textArray[i].length() > 4)
.toArray();
for (int i = indices.length; i > 1; --i) {
int j = indices[rgen.nextInt(i)];
int k = indices[i - 1];
if (j != k) {
String tmp = textArray[j];
textArray[j] = textArray[k];
textArray[k] = tmp;
}
}
return textArray;
}
OP не сказал, что нельзя использовать потоки, только коллекции. Если это проблема, можно заменить инициализацию indices простым циклом для инициализации массива int того же размера, что и textArray, используя переменную i для отслеживания количества введенных индексов (чтобы он был объявлен и инициализирован перед основным циклом for).
Вы можете добавить первый цикл, в котором будут храниться индексы слов длиной более 4 букв.