Метод toArray
Метод toArray преобразует набор элементов jQuery в массив JavaScript. Это нужно для того, чтобы к этому массиву можно было применить методы и функции JavaScript, например, отсортировать этот массив или перевернуть.
Синтаксис
Так получаем весь набор элементов:
Пример
Давайте получим все элементы с тегом p в виде массива с помощью метода toArray , перевернем его, используя reverse и выведем текстовое содержимое элементов в виде строки, используя JavaScript метод join :
Смотрите также
- метод get ,
который получает набор элементов - метод filter ,
который фильтрует элементы в наборе
Операции ToArray и ToList
Следующие операции преобразования предоставляют простой и удобный способ преобразования последовательностей в другие типы коллекций.
ToArray
Операция ToArray создает массив типа T из входной последовательности типа T. Эта операция имеет один прототип, описанный ниже:
public static Т[] ToArray( this IEnumerable source);
Эта операция берет входную последовательность source с элементами типа T и возвращает массив элементов типа Т.
Для примера, демонстрирующего работу операции ToArray, понадобится последовательность типа IEnumerable. Последовательность этого типа создается вызовом операции Enumerable.Range(), которая была описана ранее. Имея такую последовательность, можно вызывать операцию ToArray для создания массива, как показано ниже:
IEnumerable item = Enumerable.Range(1, 20); Console.WriteLine("Начальный тип: " + item); int[] arr = item.ToArray(); Console.WriteLine("Используем ToArray: " + arr);
Эта операция часто бывает удобной для кэширования последовательности, чтобы она не могла измениться до начала ее перечисления. К тому же, поскольку эта операция не является отложенной и выполняется немедленно, множество перечислений, созданных на одном массиве, всегда будут видеть одни и те же данные.
ToList
Операция ToList создает List типа T из входной последовательности типа Т. Эта операция имеет один прототип, описанный ниже:
public static List ToList( this IEnumerable source);
Данная операция принимает последовательность по имени source элементов типа T и возвращает список List элементов типа Т. Ниже демонстрируется применение операции ToList:
string[] cars = < "Alfa Romeo", "Aston Martin", "Audi", "Nissan", "Chevrolet", "Chrysler", "Dodge", "BMW", "Ferrari", "Bentley", "Ford", "Lexus", "Mercedes", "Toyota", "Volvo", "Subaru", "Жигули :)">; List auto = cars.ToList(); foreach (string s in auto) Console.Write(s + " ");
В приведенном коде используется массив, состоящий из названий машин. Этот массив преобразуется в список List. Вот результат:
Эта операция часто полезна для кэширования последовательности, чтобы она не могла измениться перед ее перечислением. Также, поскольку эта операция не является отложенной и выполняется немедленно, множество перечислений на созданном списке List всегда видят одинаковые данные.
Реализация метода default T[] toArray(T[] array)
Пытаюсь построить свой JCF (балуюсь, чтобы лучше разобраться в коллекциях). Создал класс MyList
@Override default boolean retainAll(Collection c) < removeIf(element ->!c.contains(element)); return true; > @Override default T[] toArray(T[] array) < if (array.length != size()) < array = Arrays.copyOf(array, array.length + (size() - array.length)); >for (int i = 0; i
Отслеживать
68.2k 225 225 золотых знаков 80 80 серебряных знаков 223 223 бронзовых знака
задан 20 июл 2022 в 10:56
supervitas supervitas
5 1 1 бронзовый знак
@user7860670 Вы имеете в виду: T[] newArr = new T[capacity] ? Так я же не могу создавать массив, используя тип дженерика
20 июл 2022 в 11:13
у Вас в методе toArray на входе массив объектов типа T и на выходе массив объектов типа T. так и надо? ничего не напутали? в чем смысл приводить T[ ] к T[ ] ?
20 июл 2022 в 11:55
@МихаилРебров Да, на входе T[] array и на выходе должен быть тоже T[] array . Просто если размер коллекции больше, чем переданный массив, то мне нужно создать новый массив и скопировать туда элементы коллекции. (T)get(i); — это нужно, поскольку MyList
20 июл 2022 в 12:16
я дополнил ответ. Извиняюсь что так долго. Занят на работе был + писал вам много букаф. Как проверите — отпишитесь.
21 июл 2022 в 21:37
1 ответ 1
Сортировка: Сброс на вариант по умолчанию
Создание массива параметризируемого типа(дженерика) в общем виде
Можно попробовать создать массив с помощью рефлексии
Имеем object с параметризируемым типом(дженериком) T :
T object;
Имея такие вводные можем создать массив элементов данного типа следующим образом:
T[] arr = (T[]) java.lang.reflect.Array.newInstance( object.getClass().getComponentType(), // получаем тип из класса объекта size // указываем размер массива );
Назначение метода toArray
Метод toArray создан для приведения коллекции к массиву того же типа.
В данный метод мы передаем ссылку на массив, в который мы будем записывать данные коллекции.
Если в массиве недостаточно места, то мы создаем новый и записываем его на место старого.
Если в массиве места больше чем требуется, то мы ставим нулевой элемент( null ) как метку окончания данных.
Рассмотрим имеющиеся реализации метода toArray
Для того, чтобы сделать правильную реализацию данного метода неплохо было бы заглянуть, а как они сами предлагают это сделать, на примере реализаций из ArrayList и LinkedList .
Реализация toArray(T[] a) в классе ArrayList
public T[] toArray(T[] a) < if (a.length < size) // Make a new array of a's runtime type, but my contents: return (T[]) Arrays.copyOf(elementData, size, a.getClass()); System.arraycopy(elementData, 0, a, 0, size); if (a.length >size) a[size] = null; return a; >
Напоминаю, что мы рассматриваем реализацию ArrayList и как следует из названия — это реализация интерфейса List на основе массива, что важно в контексте дальнейшего рассмотра.
Для хранения элементов списка в классе ArrayList используется поле elementData.
Сначала мы проверяем, достаточный ли размер у переданного массива, чтобы мы могли поместить в него имеющиеся элементы.
if (a.length < size)
Если размера массива недостаточно, то мы с помощью утилитарного класса Arrays делаем копию массива elementData c тем же размером и с указанием типа переданного массива ( a.getClass() )
return (T[]) Arrays.copyOf(elementData, size, a.getClass());
В противном случае мы копируем все элементы массива elementData в массив а (как и планировалось), начиная с самого начала(в данном используемый метод позволяет указать место с которого можно начать копировать и место в которое следует копировать, а также количество этих элементов).
Копируем мы с помощью утилитарного метода arraycopy в классе System
System.arraycopy(elementData, 0, a, 0, size);
Далее мы проверяем, а не больше ли переданный массив нашего списка
if (a.length > size)
Если у переданного массива размер больше необходимого, то мы ставим null в след за скопированными элементами, чтобы при итерации можно было найти конец данных и не отхватить Exception в лицо
a[size] = null;
Реализация toArray(T[] a) в классе LinkedList
public T[] toArray(T[] a) < if (a.length < size) a = (T[])java.lang.reflect.Array.newInstance( a.getClass().getComponentType(), size); int i = 0; Object[] result = a; for (LinkedList.Nodex = first; x != null; x = x.next) result[i++] = x.item; if (a.length > size) a[size] = null; return a; >
Как и в прошлом случае мы сначала проверяем, достаточный ли размер у переданного массива.
if (a.length < size)
Если размер массива недостаточен, то мы с помощью рефлексии создаем новый массив с указанным типом данных и нужным нам размером и сохраняем ссылку на него в переменную a
a = (T[])java.lang.reflect.Array.newInstance( a.getClass().getComponentType(), size);
Отмечу, что в данной реализации используется именно тот способ, который я предлагал изначально.
В отличии от первой реализации, на данном этапе у нас есть просто пустой массив достаточного размера, в то время как в прошлой мы уже возвращали новый массив для одного из обрабатываемых кейсов.
Далее нам необходимо переложить все элементы в данный массив.
Для начала мы определяем переменную в которой будет храниться индекс итерируемого элемента, т.к. в связанном списке при итерации мы имеем только ссылку на предыдущий и на следующий элемент.
int i = 0;
Далее мы создаем переменную result и кладем туда ссылку на массив a
Object[] result = a;
Вот тут уже нужна пояснительная бригада.
Делается это по всей видимости для того чтобы не заморачиваться с приведением типов.
Поэтому дабы избежать проблем и заморочек мы просто создадим еще одну ссылку, только уже объявленную как Object[] .
И туда уже нам будет разрешено класть элементы списка без какого бы то ни было приведения типов.
Причем по сути мы будем работать с тем же самым массивом.
Только условия попадения в него будут помягче:)
Такие вот финты ушами можно найти в исходниках java.lang
По сути разработчики JDK просто перекладывают ответственность на то, что вы кладете в список на Вас (а что им еще делать?).
Далее мы копируем элементы связанного списка в массив, используя при этом переменную result
for (LinkedList.Node x = first; x != null; x = x.next) result[i++] = x.item;
Здесь также стоит остановиться и рассмотреть все поподробнее.
Сначала мы в качестве итератора берём ноду связанного списка и инициализируем итератор ссылкой на первый элемент.
LinkedList.Node x = first;
В качестве условия выхода из цикла мы используем обычную проверку на null.
x != null;
Она рано или поздно там появится, потому что у последнего элемента в списке ссылка на следующий элемент списка будет отсытствовать и равна null , там мы и остановимся.
Ну и в качестве выражения перехода, мы используем получение ссылки на следующий элемент связанного списка
x = x.next
Так поочереди, получая элемент за элементом мы обойдём весь список.
И получая каждый элемент списка мы кладем его значение в массив
result[i++] = x.item;
- Как и говорилось раньше используется переменная result, но по сути мы работаем с тем же а
- мы в одну строку и получаем значение индекса элемента и увеличиваем его на единицу(он это позволяет, почему бы не воспользоваться?)
Далее как и в первом варианте мы помечаем конец данных нулевым элементом
if (a.length > size) a[size] = null;
и возвращаем массив
Ваша реализация
Для начала укажу на некоторые недочеты Вашей реализации.
Вот что Вы используете при копировании массива:
array.length + (size() - array.length)
Зачем так сложно?
Если мы опустим скобки (а они тут необязательны), то мы получим просто size() ( array.length - array.length = 0 )
Т.к. у меня нет кода всей реализации класса, я не могу за Вас полностью написать какую-то ультимативную реализацию Вашего метода toArray , как и не смогу проверить ее работоспособность, но я могу рассмотреть примеры и обратить внимание на идеи и приемы, которые используются в вышеуказанных реализациях и выдвинуть пару предложений по реализации.
Вариант
Вы можете воспользоваться тем же финтом ушами с подменой типа массива и написать что-то вроде этого:
@Override default T[] toArray(T[] array) < if (array.length != size()) < array = Arrays.copyOf(array, size()); >// сохраняем ссылку на массив в переменную с менее строгим типом Object[] result = array; for (int i = 0; i < size(); i++) < //работаем с подменой без приведения result[i] = get(i); >// но возвращаем переданную ссылку return array; >
Самому интересно сработает или нет.
Как попробуете - отпишитесь!
Что делает .ToArray() и зачем он нужен в данном коде?
Здесь я создал переменную input и переменную output . Я хотел присвоить output перевернутое значение input , почему без .ToArray() код не работает, зачем нужен .ToArray() и что он делает я не понял.
Отслеживать
6,393 6 6 золотых знаков 26 26 серебряных знаков 57 57 бронзовых знаков
задан 16 мар 2018 в 5:18
user251917 user251917
23 1 1 серебряный знак 5 5 бронзовых знаков
2 ответа 2
Сортировка: Сброс на вариант по умолчанию
Метод Reverse (как и большинство остальных методов Linq) возвращает IEnumerable , но у класса String нет конструктора, принимающего IEnumerable , зато есть конструктор, принимающий массив. Метод ToArray как раз и собирает массив на основе входной последовательности IEnumerable .
Кстати, строка реализует IEnumerable , поэтому вызывать Reverse можно прямо на ней, ToCharArray можно не вызывать.
Отслеживать
ответ дан 16 мар 2018 в 5:25
Андрей NOP Андрей NOP
28.7k 4 4 золотых знака 40 40 серебряных знаков 81 81 бронзовый знак
В качестве дополнения в правильному ответу @Андрей NOP, если ваша цель — развернуть строку, вам нужна более сложная техника.
Например, вот такой код поддерживает символы из старших плоскостей Unicode, а также ненормализуемые акценты:
static IEnumerable GetGraphemeClusters(string s) < var enumerator = StringInfo.GetTextElementEnumerator(s); while (enumerator.MoveNext()) yield return (string)enumerator.Current; >static void Main(string[] args) < string[] strings = < "Les Mise\u0301rables", "Co\u0323\u0302ng ho\u0300a xa\u0303 ho\u0323\u0302i chu\u0309 nghi\u0303a Vie\u0323\u0302t Nam", "" >; foreach (string input in strings) < string output = string.Concat(GetGraphemeClusters(input).Reverse().ToArray()); Debug.WriteLine($"-> "); > >