Форум программистов, компьютерный форум, киберфорум
Java для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.83/6: Рейтинг темы: голосов - 6, средняя оценка - 4.83
 Аватар для Coffeini
753 / 370 / 133
Регистрация: 01.02.2020
Сообщений: 1,096
Записей в блоге: 1

Метод для подсчёта размерностей массива

01.05.2021, 18:18. Показов 1210. Ответов 4

Студворк — интернет-сервис помощи студентам
Мне понадобился метод для вычисления размерностей массива. Например при аргументе new int[1][2][3][4][5] он должен возвращать массив [1,2,3,4,5]. Вроде бы я его написал и он даже работает:
Кликните здесь для просмотра всего текста
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
/**
     * @param s      string to be counted.
     * @param symbol sought symbol.
     * @return the number of sought characters in the string.
     */
    public static int calculateQuantitySymbol(String s, String symbol) {
        return s.length() - s.replace(symbol, "").length();
    }
 
    /**
     * @param array the array to calculate the depth of.
     * @return depth of the array.
     * @deprecated it seems to me that the correct answer is not always obtained.
     */
    public static int calculateDeepArray(Object array) {
        return calculateQuantitySymbol(array.getClass().getTypeName(), "[");
    }
 
    /**
     * @param array is a simple (all nested arrays at the same depth have the same size) array.
     * @return the dimensions of the array.
     * @deprecated there might be a better way to calculate.
     */
    public static int[] calculateLengthsEvenArray(Object array) {
        return calculateLengthsEvenArray(array, 0, new int[calculateDeepArray(array)]);
    }
 
    private static int[] calculateLengthsEvenArray(Object array, int deep, int[] lengths) {
        if (array instanceof boolean[]) {
            lengths[deep] = ((boolean[]) array).length;
            return lengths;
        } else if (array instanceof char[]) {
            lengths[deep] = ((char[]) array).length;
            return lengths;
        } else if (array instanceof short[]) {
            lengths[deep] = ((short[]) array).length;
            return lengths;
        } else if (array instanceof int[]) {
            lengths[deep] = ((int[]) array).length;
            return lengths;
        } else if (array instanceof long[]) {
            lengths[deep] = ((long[]) array).length;
            return lengths;
        } else if (array instanceof float[]) {
            lengths[deep] = ((float[]) array).length;
            return lengths;
        } else if (array instanceof double[]) {
            lengths[deep] = ((double[]) array).length;
            return lengths;
        } else {
            if (array.getClass().isArray()) {
                lengths[deep] = ((Object[]) array).length;
                if (lengths[deep] > 0) {
                    return calculateLengthsEvenArray(((Object[]) array)[0], deep + 1, lengths);
                }
            }
            return lengths;
        }
    }

Однако он работает только с "простыми"(не знаю как обозвать массивы, которые на каждом уровне содержат подмассивы одинаковых размеров) массивами. Поэтому пришлось сделать метод для проверки на простоту:
Кликните здесь для просмотра всего текста
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
/**
     * @param array the array to be checked for simplicity (all nested arrays at the same depth have the same size)
     * @return whether the array is simple
     */
    public static boolean isEvenArray(Object array) {
        int[] result = new int[calculateDeepArray(array)];
        Arrays.fill(result, -1);
        return isEvenArray(array, 0, result);
    }
    private static boolean isEvenArray(Object array, int deep, int[] lengths) {
        if (array == null) {
            return false;
        } else if (array instanceof boolean[]) {
            if (lengths[deep] == -1) {
                lengths[deep] = ((boolean[]) array).length;
            } else return lengths[deep] == ((boolean[]) array).length;
        } else if (array instanceof char[]) {
            if (lengths[deep] == -1) {
                lengths[deep] = ((char[]) array).length;
            } else return lengths[deep] == ((char[]) array).length;
        } else if (array instanceof short[]) {
            if (lengths[deep] == -1) {
                lengths[deep] = ((short[]) array).length;
            } else return lengths[deep] == ((short[]) array).length;
        } else if (array instanceof int[]) {
            if (lengths[deep] == -1) {
                lengths[deep] = ((int[]) array).length;
            } else return lengths[deep] == ((int[]) array).length;
        } else if (array instanceof long[]) {
            if (lengths[deep] == -1) {
                lengths[deep] = ((long[]) array).length;
            } else return lengths[deep] == ((long[]) array).length;
        } else if (array instanceof float[]) {
            if (lengths[deep] == -1) {
                lengths[deep] = ((float[]) array).length;
            } else return lengths[deep] == ((float[]) array).length;
        } else if (array instanceof double[]) {
            if (lengths[deep] == -1) {
                lengths[deep] = ((double[]) array).length;
            } else return lengths[deep] == ((double[]) array).length;
        } else if (array.getClass().isArray()) {
            if (lengths[deep] == -1) {
                lengths[deep] = ((Object[]) array).length;
            } else if (lengths[deep] != ((Object[]) array).length) {
                return false;
            }
            if (lengths[deep] > 0) {
                if (lengths[deep] == -1) {
                    lengths[deep] = ((Object[]) array).length;
                } else if (lengths[deep] != ((Object[]) array).length) {
                    return false;
                }
                ++deep;
                if (deep != 1) {
                    for (Object array1 : ((Object[]) array)) {
                        if (array1.getClass().isArray()) {
                            isEvenArray(array1, deep, lengths);
                        }
                    }
                } else {
                    boolean res = true;
                    for (Object array1 : ((Object[]) array)) {
                        if (!isEvenArray(array1, deep, lengths)) {
                            res = false;
                        }
                    }
                    return res;
                }
            }
        }
        return true;
    }

Но возникает вопрос: не существует ли более оптимальных способов вычисления? Возможно в Java уже предусмотрены методы, которые я написал.

P.S. пишу на Java 1.8, поэтому instanseof не возвращает новый экземпляр проверяемого объекта.
P.S.S. извините за постоянные повторы слов...
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
01.05.2021, 18:18
Ответы с готовыми решениями:

Как можно описать метод Крамера динамически для разных размерностей
Как можно описать метод Крамера динамически для разных размерностей Не знаю как detA = masA * masA * masA + masA * masA *...

Время работы сортировки вставками для разных размерностей массива
Друзья, подскажите: в чём проблема? Нужны временные показания работы сортировки с различными размерностями массива, для построения графика....

Метод подсчета количества элементов двумерного массива кратных заданному числу
1. Написать метод подсчета количества элементов двумерного массива кратных заданному числу. 2. Перегрузить разработанный метод для...

4
 Аватар для Tavashi
1172 / 762 / 194
Регистрация: 21.05.2016
Сообщений: 1,858
01.05.2021, 21:34
Java
1
2
3
4
5
6
7
8
9
10
11
12
    public static void main(String args[]) {
        System.out.println(Arrays.toString(calculateDeepArray(new int[1][2][3][4][5], new ArrayList<Object>()).toArray()));
    }
    
    public static List<Object> calculateDeepArray(Object obj, List<Object> list) {
        if (obj != null && obj.getClass().isArray()) {
            list.add(Array.getLength(obj));
            calculateDeepArray(Array.get(obj, 0), list);
        }
        
        return list;
    }
2
 Аватар для Coffeini
753 / 370 / 133
Регистрация: 01.02.2020
Сообщений: 1,096
Записей в блоге: 1
01.05.2021, 22:02  [ТС]
Tavashi, не знаю зачем мне нужны листы, если я и так знаю глубину массива, а вот про методы в классе Array я не знал, спасибо. В принципе-то так код стал проще, но вряд ли сильно ускорился.
new calculateLengthsEvenArray()
Java
1
2
3
4
5
6
7
private static int[] calculateLengthsEvenArray(Object array, int deep, int[] lengths) {
        if (array != null && array.getClass().isArray()) {
            lengths[deep] = Array.getLength(array);
            calculateLengthsEvenArray(Array.get(array, 0), deep + 1, lengths);
        }
        return lengths;
}

new isEvenArray()
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
private static boolean isEvenArray(Object array, int deep, int[] lengths) {
        if (array == null) {
            return false;
        } else if (array.getClass().isArray()) {
            if (lengths[deep] == -1) {
                lengths[deep] = Array.getLength(array);
            } else if (lengths[deep] != Array.getLength(array)) {
                return false;
            }
            if (lengths[deep] > 0) {
                ++deep;
                boolean res = true;
                int length = Array.getLength(array);
                for (int i = 0; i < length; ++i) {
                    if (!isEvenArray(Array.get(array, i), deep, lengths)) {
                        res = false;
                    }
                }
                return res;
            }
        }
        return true;
    }

Поэтому вопрос остался тот же: можно ли это хоть как-то оптимизировать?
По факту метод isEvenArray() порождает огромный стек рекурсии... И если мне надо часто вызывать его, то как-то медленно выходит, наверное.
0
 Аватар для Tavashi
1172 / 762 / 194
Регистрация: 21.05.2016
Сообщений: 1,858
01.05.2021, 22:10
Цитата Сообщение от Coffeini Посмотреть сообщение
не знаю зачем мне нужны листы,
Чтобы добавлять элементы динамически.
Цитата Сообщение от Coffeini Посмотреть сообщение
если я и так знаю глубину массива,
Тогда в чем вопрос?
0
 Аватар для Coffeini
753 / 370 / 133
Регистрация: 01.02.2020
Сообщений: 1,096
Записей в блоге: 1
02.05.2021, 03:34  [ТС]
Цитата Сообщение от Tavashi Посмотреть сообщение
Тогда в чем вопрос?
Цитата Сообщение от Coffeini Посмотреть сообщение
не существует ли более оптимальных способов вычисления?
Короче, как оптимизировать метод isEvenArray() и calculateLengthsEvenArray().

Вообще глянул реализацию в Class и изменил свой метод поиска глубины:
new calculateDeepArray()
Java
1
2
3
4
5
6
7
8
9
10
11
/**
 * @param array the array to calculate the depth of.
 * @return depth of the array.
 * @deprecated it seems to me that the correct answer is not always obtained.
 */
public static int calculateDeepArray(Object array) {
    int i;
    Class c = array.getClass();
    for (i = 0; c.isArray(); c = c.getComponentType(), ++i) ;
    return i;
}


Добавлено через 5 часов 15 минут
Изменил тип расчёта с рекурсивного на итерационный:
Кликните здесь для просмотра всего текста
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
/**
 * @param array is a simple (all nested arrays at the same depth have the same size) array.
 * @return the dimensions of the array.
 * @deprecated there might be a better way to calculate.
 */
public static int[] calculateLengthsEvenArray(Object array) {
    int[] lengths = new int[calculateDeepArray(array)];
    Object tempLink = array;
    lengths[0] = Array.getLength(array);
    for (int i = 1; i < lengths.length; ++i) {
        lengths[i] = Array.getLength((tempLink = Array.get(tempLink, 0)));
    }
    return lengths;
}
 
/**
 * @param array the array to be checked for simplicity (all nested arrays at the same depth have the same size)
 * @return whether the array is simple
 */
public static boolean isEvenArray(Object array) {
    int[] lengths = new int[calculateDeepArray(array)], indexed = new int[lengths.length - 1];
    Arrays.fill(lengths, -1);
    Object[] tempLinks = new Object[lengths.length];
    tempLinks[0] = array;
    int arrow = 1;
 
    mainLoop:
    while (true) {
        tempLinks[arrow] = Array.get(tempLinks[arrow - 1], indexed[arrow - 1]);
        if (tempLinks[arrow] == null) {
            return false;
        }
        if (lengths[arrow] == -1) {
            lengths[arrow] = Array.getLength(tempLinks[arrow]);
        } else if (lengths[arrow] != Array.getLength(tempLinks[arrow])) {
            return false;
        }
 
        if (arrow < lengths.length - 1) {
            ++arrow;
        } else {
            ++indexed[arrow - 1];
        }
 
        while (Array.getLength(tempLinks[arrow - 1]) <= indexed[arrow - 1]) {
            if (--arrow != 0) {
                indexed[arrow] = 0;
                ++indexed[arrow - 1];
            } else {
                break mainLoop;
            }
        }
    }
    return true;
}


Интересно, сильно ли повлияли такие изменения и стоили они того....
Возможно ли ещё как-то оптимизировать эти методы? Или остается только распараллелить расчёты?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
02.05.2021, 03:34
Помогаю со студенческими работами здесь

Метод для подсчета строк в textBox
Доброго времени суток! Помогите написать метод, который бы определял, произошёл ли переход на новую строку Вот код заголовочного...

Описать метод для подсчёта стоимости заказа
a) Разработать класс с соответствующими полями b) Предусмотреть инициализацию с проверкой допустимости значений полей. В случае...

Написать метод для подсчета количества цифр в числе
Написать метод для подсчета количества цифр в числе.

Метод для подсчета, сколько денег получает работник в неделю
Привет, задали задание помогите сделать. Создайте метод, который будет считать сколько денег получает работник в неделю. Метод должен...

Как использовать метод для подсчёта количества способов отбора по формуле?
Определить, сколькими способами можно отобрать команду в составе пяти человек из восьми кандидатов; из 10 кандидатов; из 11 кандидатов....


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
5
Ответ Создать тему
Новые блоги и статьи
Контроль заполнения и очистка дат в зависимости от значения перечислений
Maks 12.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "ПланированиеПерсонала", разработанного в конфигурации КА2. Задача: реализовать контроль корректности заполнения дат назначения. . .
Архитектура слоя интернета для сервера-слоя.
Hrethgir 11.04.2026
В продолжение https:/ / www. cyberforum. ru/ blogs/ 223907/ 10860. html Знаешь что я подумал? Раз мы все источники пишем в голове ветки, то ничего не мешает добавить в голову такой источник, который сам. . .
Подстановка значения реквизита справочника в табличную часть документа
Maks 10.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "ПланированиеПерсонала", разработанного в конфигурации КА2. Задача: при выборе сотрудника (справочник Сотрудники) в ТЧ документа. . .
Очистка реквизитов документа при копировании
Maks 09.04.2026
Алгоритм из решения ниже применим как для типовых, так и для нетиповых документов на самых различных конфигурациях. Задача: при копировании документа очищать определенные реквизиты и табличную. . .
модель ЗдравоСохранения 8. Подготовка к разному выполнению заданий
anaschu 08.04.2026
https:/ / github. com/ shumilovas/ med2. git main ветка * содержимое блока дэлэй из старой модели теперь внутри зайца новой модели 8ATzM_2aurI
Блокировка документа от изменений, если он открыт у другого пользователя
Maks 08.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа, разработанного в конфигурации КА2. Задача: запретить редактирование документа, если он открыт у другого пользователя. / / . . .
Система безопасности+живучести для сервера-слоя интернета (сети). Двойная привязка.
Hrethgir 08.04.2026
Далее были размышления о системе безопасности. Сообщения с наклонным текстом - мои. А как нам будет можно проверить, что ссылка наша, а не подделана хулиганами, которая выбросит на другую ветку и. . .
Модель ЗдрввоСохранения 7: больше работников, больше ресурсов.
anaschu 08.04.2026
работников и заданий может быть сколько угодно, но настроено всё так, что используется пока что только 20% kYBz3eJf3jQ
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru