Вывод нечётных элементов массива через запятую

422
22 мая 2021, 21:20

Условие задачи:

Напишите метод printOddNumbers, который принимает массив и выводит в консоль только нечётные числа из него через запятую. Конец вывода должен перевести курсор на новую строку.

Пример ввода: [3,5,20,8,7,3,100]

Пример вывода: 3, 5, 7, 3

public class Main {
    public static void main(String[] args) {
        int[] arr = {2, 5, 5, 5, 8, 4, 5, 6, 8, 5};
        printOddNumbers(arr);
    }
    public static void printOddNumbers(int[] arr) {
        for (int x = 0; x < arr.length; x++)
            if (arr[x] % 2 != 0)
                System.out.print(arr[x] + ", ");
    }
}

Вывод такой: 5, 5, 5, 5, 5,

Я не могу понять, как оформить решение так, чтобы последняя запятая не выводилась, наверное, я уже устал и не вижу очевидного решения. Буду благодарен, если кто-то также подскажет решение покороче.

Answer 1

Очевидно, что лучшим вариантом является вариант с поиском первого нечётного числа (8),

ну либо вариант с Regex (10), если вы извращенец.

(1) Вариант со стримом-фильтровальщиком.

public static void printOddNumbers(int[] arr) {
    arr = IntStream.of(arr).filter(i -> (i & 1) == 1).toArray();
    StringBuilder sb = new StringBuilder();
    if(arr.length != 0)
        sb.append(arr[0]);
    for (int i = 1; i < arr.length; i++)
        sb.append(", ").append(arr[i]);
    System.out.println(sb);
}

(2) Вариант только со стримом.

public static void printOddNumbers(int[] arr) {
    System.out.println(IntStream.of(arr)
            .filter(i -> (i & 1) == 1)
            .mapToObj(Integer::toString)
            .collect(Collectors.joining(", ")));
}

Варианты со списком.

(3) Объединение элементов вручную.

public static void printOddNumbers(int[] arr) {
    ArrayList<Integer> list = new ArrayList<>();
    for (int i : arr)
        if((i & 1) == 1)
            list.add(i);
    StringBuilder sb = new StringBuilder();
    // такой способ соединения с разделителем используется в методе Arrays.toString()
    int limit = list.size() - 1;
    if(limit != -1)
        for (int i = 0;; i++) {
            sb.append(list.get(i));
            if(i == limit)
                break;
            sb.append(", ");
        }
    System.out.println(sb);
}

(4) Объединение с помощью метода String.join(CharSequence, Iterable<? extends CharSequence>). (видоизменённая реализация Qwertiy)

public static void printOddNumbers(int[] arr) {
    ArrayList<String> list = new ArrayList<>();
    for (int i : arr)
        if ((i & 1) == 1)
            list.add(i + "");
    System.out.print(String.join(", ", list));
}

(5) Вариант с обрезанием возвращаемого значения метода List.toString().

public static void printOddNumbers(int[] arr) {
    ArrayList<Integer> list = new ArrayList<>();
    for (int i : arr)
        if((i & 1) == 1)
            list.add(i);
    String toPrint = list.toString();
    System.out.println(toPrint.substring(1, toPrint.length() - 1));
}

(6) Вариант со StringJoiner.

public static void printOddNumbers(int[] arr) {
    StringJoiner joiner = new StringJoiner(", ");
    for (int i : arr)
        if ((i & 1) == 1)
            joiner.add(i + "");
    System.out.println(joiner.toString());
}

(7) Вариант с boolean переменной.

public static void printOddNumbers(int[] arr) {
    boolean firstAdded = false;
    StringBuilder sb = new StringBuilder();
    for (int i : arr)
        if((i & 1) == 1) {
            if(firstAdded)
                sb.append(", ");
            else
                firstAdded = true;
            sb.append(i);
        }
    System.out.println(sb);
}

(8) Вариант с поиском первого нечётного числа. (Самый быстрый)

public static void printOddNumbers(int[] arr) {
    StringBuilder sb = new StringBuilder();
    int i = 0;
    for (; i < arr.length; i++)
        if((arr[i] & 1) == 1) {
            sb.append(arr[i++]);
            break;
        }
    for (; i < arr.length; i++)
        if((arr[i] & 1) == 1)
            sb.append(", ").append(arr[i]);
    System.out.println(sb);
}

(9) Вариант с поиском последнего нечётного числа.

public static void printOddNumbers(int[] arr) {
    int limit = -1;
    for (int i = arr.length - 1; limit == -1; i--)
        if((arr[i] & 1) == 1)
            limit = i;
    StringBuilder sb = new StringBuilder();
    for (int i = 0;; i++)
        if((arr[i] & 1) == 1) {
            sb.append(arr[i]);
            if(i < limit)
                sb.append(", ");
            else
                break;
        }
    System.out.println(sb);
}

(10) Вариант с Regex.

public static void printOddNumbers(int[] arr) {
    System.out.println(Arrays.toString(arr).replaceAll(", \\d*[02468](?!\\d)|\\d*[02468](?:, |])|[\\[\\]]",""));
}

Варианты с обрезанием запятой.

(11) Первой.

public static void printOddNumbers(int[] arr) {
    StringBuilder sb = new StringBuilder();
    for (int i : arr)
        if((i & 1) == 1)
            sb.append(", ").append(i);
    System.out.println(sb.isEmpty() ? sb : sb.substring(2));
}

(12) Последней. (Идея rjhdby)

public static void printOddNumbers(int[] arr) {
    StringBuilder sb = new StringBuilder();
    for (int i : arr)
        if((i & 1) == 1)
            sb.append(i).append(", ");
    if (!sb.isEmpty())
        sb.setLength(sb.length() - 2);
    System.out.println(sb);
}

(13) Вариант с сепаратором. (Идея aleksandr barakin)

public static void printOddNumbers(int[] arr) {
    StringBuilder sb = new StringBuilder();
    String separator = "";
    for (int i : arr)
        if ((i & 1) == 1) {
            sb.append(separator).append(i);
            if (separator.isEmpty())
                separator = ", ";
        }
    System.out.println(sb);
}

(14) Вариант с компиляцией строки при помощи методов анонимного класса.

public static void printOddNumbers(int[] arr) {
    System.out.println(new Object() {
        StringBuilder compile() {
            StringBuilder sb = new StringBuilder();
            int i = getNextIndex(0);
            if(i != -1) while(true) {
                sb.append(arr[i]);
                i = getNextIndex(i + 1);
                if(i == -1)
                    break;
                sb.append(", ");
            }
            return sb;
        }
        int getNextIndex(int index) {
            for (int i = index; i < arr.length; i++)
                if((arr[i] & 1) == 1)
                    return i;
            return -1;
        }
    }.compile());
}

(15) Варианты с рекурсией и обрезанием массива с начала.

(На самом деле есть ещё два варианта с обрезанием массива с конца, но они настолько похожи на эти, что я решил их не включать)

С помощью индекса.

public static void printOddNumbers(int[] arr) {
    System.out.println(new Object() {
        StringBuilder recursion(int[] array, int startIndex) {
            if (array.length == startIndex)
                return new StringBuilder();
            if ((array[startIndex] & 1) == 1) {
                StringBuilder result = new StringBuilder().append(array[startIndex]);
                StringBuilder sb = recursion(array, startIndex + 1);
                if (sb.length() != 0)
                    result.append(", ").append(sb);
                return result;
            } else
                return recursion(array, startIndex + 1);
            }
    }.recursion(arr, 0));
}

С помощью копирования массивов.

public static void printOddNumbers(int[] arr) {
    System.out.println(new Object() {
        int[] cropFirstElement(int[] array) {
            int[] result = new int[array.length-1];
            System.arraycopy(array, 1, result, 0, result.length);
            return result;
        }
        StringBuilder recursion(int[] array) {
            if (array.length == 0)
                return new StringBuilder();
            if ((array[0] & 1) == 1) {
                StringBuilder result = new StringBuilder().append(array[0]);
                StringBuilder sb = recursion(cropFirstElement(array));
                if (sb.length() != 0)
                    result.append(", ").append(sb);
                return result;
            } else
                return recursion(cropFirstElement(array));
        }
    }.recursion(arr));
}

(16) Варианты с рекурсией и ополовиниванием массива.

С помощью индексов.

public static void printOddNumbers(int[] arr) {
    System.out.println(arr.length == 0 ? "" : new Object() {
        StringBuilder recursion(int[] array, int startIndex, int endIndex) {
            if (endIndex - startIndex == 1)
                if ((array[startIndex] & 1) == 1)
                    return new StringBuilder(array[startIndex] + "");
                else
                    return new StringBuilder();
            StringBuilder sb1 = recursion(array, startIndex, startIndex + (endIndex - startIndex) / 2),
                    sb2 = recursion(array, startIndex + (endIndex - startIndex) / 2, endIndex);
            if (sb2.isEmpty())
                return sb1;
            else
                return sb1.append(", ").append(sb2);
        }
    }.recursion(arr, 0, arr.length));
}

С помощью копирования массивов.

public static void printOddNumbers(int[] arr) {
    System.out.println(arr.length == 0 ? "" : new Object() {
        StringBuilder recursion(int[] array) {
            if (array.length == 1)
                if ((array[0] & 1) == 1)
                    return new StringBuilder(array[0] + "");
                else
                    return new StringBuilder();
            int halfOfLength = array.length / 2;
            int[] arr1 = new int[halfOfLength],
                    arr2 = new int[array.length - halfOfLength];
            System.arraycopy(array, 0, arr1, 0, arr1.length);
            System.arraycopy(array, halfOfLength, arr2, 0, arr2.length);
            StringBuilder sb1 = recursion(arr1),
                    sb2 = recursion(arr2);
            if (sb2.isEmpty())
                return sb1;
            else
                return sb1.append(", ").append(sb2);
        }
    }.recursion(arr));
}

(17) Вариант с созданием нового массива из нечётных чисел вручную.

public static void printOddNumbers(int[] arr) {
    int lim = 0;
    int[] oddArr = new int[arr.length];
    for (int i : arr)
        if((i & 1) == 1)
            oddArr[lim++] = i;
    StringBuilder sb = new StringBuilder();
    if(--lim != -1)
        for (int i = 0;; i++) {
            sb.append(oddArr[i]);
            if(i == lim)
                break;
            sb.append(", ");
        }
    System.out.println(sb);
}

(18) Вариант с проверкой длины (пустоты) StringBuilder(а).

public static void printOddNumbers(int[] arr) {
    StringBuilder sb = new StringBuilder();
    for (int i : arr)
        if((i & 1) == 1)
            sb.append(sb.isEmpty() ? "" : ", ").append(i);
    System.out.println(sb);
}

(19) Вариант с двойным пробеганием массива и сохранением количества нечётных чисел.

public static void printOddNumbers(int[] arr) {
    int count = 0;
    for (int i : arr)
        if ((i & 1) == 1)
            count++;
    StringBuilder sb = new StringBuilder();
    for (int i : arr)
        if ((i & 1) == 1) {
            sb.append(i);
            if (--count == 0)
                break;
            sb.append(", ");
        }
    System.out.println(sb);
}

(20) Вариант с пробеганием массива с двух сторон.

public static void printOddNumbers(int[] arr) {
    StringBuilder sb1 = new StringBuilder(),
            sb2 = new StringBuilder();
    int index1 = 0, index2 = arr.length - 1;
    while (index1 < index2) {
        if ((arr[index1] & 1) == 1)
            sb1.append(arr[index1]).append(", ");
        index1++;
        if ((arr[index2] & 1) == 1)
            sb2.insert(0, ", " + arr[index2]);
        index2--;
    }
    if (index1 == index2 && (arr[index1] & 1) == 1)
        System.out.println(sb1.append(arr[index1]).append(sb2));
    else if (sb2.length() > 0)
        System.out.println(sb1.append(sb2.substring(2)));
    else
        System.out.println(sb1);
}

(21) Вариант с пробеганием массива в обе стороны из середины.

public static void printOddNumbers(int[] arr) {
    StringBuilder sb1 = new StringBuilder(),
            sb2 = new StringBuilder();
    int index1 = arr.length / 2 - 1 /* '- 1' на случай, если массив пустой */,
            index2 = index1 + 1;
    while (index1 > -1) {
        if ((arr[index1] & 1) == 1)
            sb1.insert(0, arr[index1] + ", ");
        index1--;
    }
    while (index2 < arr.length) {
        if ((arr[index2] & 1) == 1)
            sb2.append(", ").append(arr[index2]);
        index2++;
    }
    if (sb2.isEmpty())
        System.out.println(sb1);
    else
        System.out.println(sb1.append(sb2.substring(2)));
}

(22) Совсем ненормальный вариант с regex и двумя стримами один в другом.

public static void printOddNumbers(int[] arr) {
    System.out.println(
            Stream.of(
                    IntStream.of(arr)
                    .mapToObj(Integer::toString)
                    .collect(Collectors.joining(","))
                    .split("(?<=[13579]),(?=\\d*[13579](?!\\d))|(?:,|^)(?:\\d*[02468](?:,|$))+")
            ).filter(s -> !s.isEmpty())
            .collect(Collectors.joining(", "))
    );
}

(23) Вариант с вырезанием всех чётных чисел.

public static void printOddNumbers(int[] arr) {
    for (int i = 0; i < arr.length;)
        if ((arr[i] & 1) == 0) {
            int[] newArr = new int[arr.length-1];
            System.arraycopy(arr, 0, newArr, 0, i);
            System.arraycopy(arr, i + 1, newArr, i, newArr.length - i);
            arr = newArr;
        } else
            i++;
    StringBuilder sb = new StringBuilder();
    if (arr.length > 0)
        for (int i = 0;;) {
            sb.append(arr[i]);
            if (++i == arr.length)
                break;
            sb.append(", ");
        }
    System.out.println(sb);
}

(24) Вариант с переносом всех нечётных чисел в начало массива.

public static void printOddNumbers(int[] arr) {
    int index = 0;
    for (; index < arr.length; index++)
        if ((arr[index] & 1) == 0)
            break;
    for (int i = index + 1; i < arr.length; i++)
        if ((arr[i] & 1) == 1 && i != index) {
            // arr[index++] = arr[i] - (arr[i] = 0);
            arr[index] = arr[i];
            arr[i] = 0; // любое чётное число
            index++;
        }
    StringBuilder sb = new StringBuilder();
    if (index != 0)
        sb.append(arr[0]);
    for (int i = 1; i < index; i++)
        sb.append(", ").append(arr[i]);
    System.out.println(sb);
}

(25) Вариант с конечным автоматом.

public static void printOddNumbers(int[] arr) {
    class FSM {
        final int NOT_FOUNT_FIRST_ODD_NUMBER_YET = 0;
        final int AT_FIRST_ODD_NUMBER = 1;
        final int AT_ODD_NUMBER = 2;
        final int AT_EVEN_NUMBER = 3;
        final int AT_THE_END_OF_THE_ARRAY = 4;
        int currentState = NOT_FOUNT_FIRST_ODD_NUMBER_YET;
        void NOT_FOUNT_FIRST_ODD_NUMBER_YET() {
            if (incrementAndCheckIndex())
                if ((arr[index] & 1) == 1)
                    currentState = AT_FIRST_ODD_NUMBER;
        }
        void AT_FIRST_ODD_NUMBER() {
            result.append(arr[index]);
            setEvenOrOddState();
        }
        void AT_ODD_NUMBER() {
            result.append(", ").append(arr[index]);
            setEvenOrOddState();
        }
        void AT_EVEN_NUMBER() {
            setEvenOrOddState();
        }
        boolean incrementAndCheckIndex() {
            if (++index == arr.length) {
                currentState = AT_THE_END_OF_THE_ARRAY;
                return false;
            }
            return true;
        }
        void setEvenOrOddState() {
            if (incrementAndCheckIndex())
                currentState = (arr[index] & 1) == 1 ? AT_ODD_NUMBER : AT_EVEN_NUMBER;
        }
        void update() {
            if (currentState == NOT_FOUNT_FIRST_ODD_NUMBER_YET)
                NOT_FOUNT_FIRST_ODD_NUMBER_YET();
            else if (currentState == AT_FIRST_ODD_NUMBER)
                AT_FIRST_ODD_NUMBER();
            else if (currentState == AT_ODD_NUMBER)
                AT_ODD_NUMBER();
            else if (currentState == AT_EVEN_NUMBER)
                AT_EVEN_NUMBER();
        }
        int index = -1;
        StringBuilder result = new StringBuilder();
        StringBuilder compile() {
            while (currentState != AT_THE_END_OF_THE_ARRAY)
                update();
            return result;
        }
    }
    System.out.println(new FSM().compile());
}
Answer 2

Enterprise version

public class MyClass {
    public static void main(String args[]) {
      int[] array = new int[]{5,2,4,7,6,6,9};
      printOdds(array);
    }
    private static void printOdds(int[] array) {
      SignificantNumber[] temporalyArray = convertToSignificantNumberArray(array);
      populateWithPrefixSelector(temporalyArray);
      StringBuffer preparedString = prepareString(temporalyArray);
      System.out.print(preparedString.toString());
    }
    private static void populateWithPrefixSelector(SignificantNumber[] temporalyArray) {
        boolean firstMarked = false;
        for(int i=0; i<temporalyArray.length; i++){
          if(temporalyArray[i].isSuitable() && !firstMarked){
              temporalyArray[i].setPrefixSelector(Order.FIRST);
              firstMarked = true;
          } else {
              temporalyArray[i].setPrefixSelector(Order.OTHER);
          }
      }
    }
    private static SignificantNumber[] convertToSignificantNumberArray(int[] array){
        SignificantNumber[] temporalyArray = new SignificantNumber[array.length];
        for(int i=0; i<array.length; i++) {
          temporalyArray[i] = new SignificantNumber(array[i]);
        }
        return temporalyArray;
    }
    private static StringBuffer prepareString(SignificantNumber[] temporalyArray) {
        StringBuffer stringBuffer = new StringBuffer();
        for(int i=0; i<temporalyArray.length; i++) {
            stringBuffer.append(temporalyArray[i].getPrefixForValue());
            stringBuffer.append(temporalyArray[i].getValueAsString());
        }
        return stringBuffer;
    }
}
class SignificantNumber 
implements SuitableValueForPrintInterface, 
ValueWithPrintablePrefix<Order>,
PrintableValue {
    int number;
    Order order;
    SignificantNumber(int number){
        this.number = number;
    }
    public void setPrefixSelector(Order order){
        this.order = order;
    }
    public boolean isSuitable() {
        return andWrapper(number) == 1;
    }
    public String getPrefixForValue() {
        if(isSuitable() && !isFirst()) {
            return ", ";
        }
        return "";
    }
    public String getValueAsString() {
        if(isSuitable()){
            return Integer.toString(number);
        } else {
            return "";
        }
    }
    private int andWrapper(int number) {
        return number & 1;
    }
    private boolean isFirst() {
        return this.order == Order.FIRST;
    }
}
enum Order{
    FIRST, OTHER;
}
interface  SuitableValueForPrintInterface {
    public boolean isSuitable();
}
interface ValueWithPrintablePrefix<T> {
    public void setPrefixSelector(T prefixSelector);
    public String getPrefixForValue();
}
interface PrintableValue {
    public String getValueAsString();
}
Answer 3

Вариант через итерацию

public class Main {
    public static void main(String[] args) {
        int[] arr = {2, 1, 4, 3, 2, 2, 2};
        printOddNumbers(arr);
    }
    public static void printOddNumbers(int[] arr) {
        boolean flag == true;        
        for (int x = 0; x < arr.length; x++) {
            if(arr[x]%2 != 0){
                if(flag){
                    System.out.print(arr[x]); 
                    flag = false;                   
                }else{
                    System.out.print(", " + arr[x]);
                }
            }
        }       
        System.out.println();
    }    
}
Answer 4

Запятую надо ставить не после, а до элемента:

int[] arr = {2, 5, 5, 5, 8, 4, 5, 6, 8, 5};
String separator = ""; // перед первым элементом ничего не надо
for (int i = 0; i < arr.length; i++) {
    if (arr[i] % 2 != 0) {
        System.out.print(separator); // сначала разделитель
        System.out.print(arr[i]);    // потом элемент
        // if (separator.isEmpty())
        separator = ", ";            // разделитель перед всеми последующими
    }
}
System.out.println();
Answer 5

Иногда мудрить не надо: https://ideone.com/AfmyyZ

import java.util.*;
class Ideone {
  public static void main(String[] args) {
    printOddNumbers(new int[] {3, 5, 20, 8, 7, 3, 100});
  }
  public static void printOddNumbers(int[] arr) {
    var res = new ArrayList<String>();
    for (int x : arr) {
      if (x % 2 != 0) {
        res.add(Integer.toString(x));
      }
    }
                
    System.out.print(String.join(", ", res));
  }
}
READ ALSO
получение reactions в slack

получение reactions в slack

Как получить reactions в Slack зная его timeStamp? Используя JavaУ меня бот видит новые сообщения и всю информацию об сообщении, но обратиться к старому...

110
hibernate many to many и ошибка java.sql.SQLIntegrityConstraintViolationException: Duplicate entry

hibernate many to many и ошибка java.sql.SQLIntegrityConstraintViolationException: Duplicate entry

Есть унаследованная база данных, пытаюсь построить вокруг нее приложениеПроблема в том что я получаю периодически Duplicate entry при попытке вставить...

132
Почему именно system.out?

Почему именно system.out?

Почему когда мы хотим вывести текст на языке java мы пишем systemout ? что это значит, может кто помочь ?

106