Совсем глупый вопрос по C# - вырезать кусок из массива

kruzer25

Есть массив T[], хочется из него вырезать кусок начиная с offset из count элементов и передать другой функции, которая ожидает T[]. Что-то вроде пхпшного array_slice.
Это смешно, но я не нашёл в документации по BCL ничего такого. У Array нет таких методов. У ArraySegment нет никакого метода вроде ToArray (это меня просто поразило а передать ArraySegment<T> функции, ожидающей T[], нельзя.
Неужели надо создавать новый массив руками?

Dasar


items.Skip(offset).Take(count).ToArray

Helga87

А тут с выделением памяти все хорошо? Или лишка выделяется? Сколько памяти выделится, если окошком длины K надо будет проехаться по массиву длины L? KN или KN^2?
Тот же вопрос про количество операций (т.к. похоже, что там yield return внутри)

Dasar

Skip и Take - это yield-ы, и соответственно память они не выделяют.

Helga87

Да, я уже увидел и поправил пост. Сорри, что не новым. Что там с количеством операций?

kruzer25

Как-то подозрительно смахивает на нечто вроде Linq... оно в 2.0 работать будет?
Items - это исходный массив?
У меня просто компьютер уже выключен, посмотреть не могу.

Dasar

с операциями хуже: offset+count инкрементов и count копирований, т.е. инфа о том, что на входе массив (а не IEnumerable) - не используется.

Dasar

для 2.0 все проще:

var newArray = new Item[count];
Array.Copy(oldArray, offset, newArray, 0, count)

kruzer25

О, похоже, то, что нужно.
Правда, смущает эта низкоуровневость - вместо
var newArray = new Item[count];
Array.Copy(oldArray, offset, newArray, 0, count)

было бы логичнее сделать что-то вроде

Item[] newArray = oldArray.Copy(offset, count);

, а то выглядит как си какое-то.

Helga87

с операциями хуже: offset+count инкрементов и count копирований, т.е. инфа о том, что на входе массив (а не IEnumerable) - не используется.
Вот мне чем имплементация Linq и не нравится. Хочется отсутствие выделения лишней памяти (тут как минимум в ToArray и гарантированной линейности.
Можно ведь было скомпилировать это в нужную процедуру.
.... и это мысль! :)

Dasar

дык, Array - один из первых классов.
вроде еще даже .net-а как такого не было, когда он проектировался, это еще чуть ли не под COM делалось.

kruzer25

вроде еще даже .net-а как такого не было, когда он проектировался, это еще чуть ли не под COM делалось.
Ну так могли бы к 1.0 (или хотя бы 2.0) сделать что-нибудь приличное.
.NET ведь позиционируется как такая очень удобная и высокоуровневая платформа для разработки - а тут говорят "знаете, вот только работа с массивами у нас сделана через зад, потому что проектировали эту либу мы десять лет назад, когда о .NET-е и не слышал никто".
Можно было бы ещё сишные библиотеки взять и тоже говорить "а мы что, тут вообще никто не виноват, просто либы за 20 лет до .NET-а писались".
Но, в общем-то, теперь понятно, почему в Array и некоторых других местах многие вещи сделаны через жопу.

bleyman

Ну так возьми и напиши, мешает кто?
	public static T[] Slice<T>(this T[] arr, int offset, int length)
{
T[] slice = new T[length];
Array.Copy(arr, offset, slice, 0, length);
return slice;
}

Ну, только я бы для себя использовал питоновскую нотацию, версию, работающую с IList, и, возможно, возвращение обёртки-прокси вместо копирования.
Да, на всякий случай: компилятор C# 3.0 замечательно таргетит 2.0 фреймворк, но чтобы заработали экстенжен методы нужно куда-нибудь себе добавить
namespace System.Runtime.CompilerServices
{
[AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Method)]
public class ExtensionAttribute : Attribute
{
}
}

а чтобы был линк, нужно его аккуратно выдрать при помощи рефлектора и чьей-то матери из соответствующей дллки. Или попиздить из Моно, но у них я что-то не нашёл его.

Dasar

Да, на всякий случай: компилятор C# 3.0 замечательно таргетит 2.0 фреймворк, но чтобы заработали экстенжен методы нужно куда-нибудь себе добавить
можно просто добавить в поставку System.Core.
targeting при этом будет 3.0, но запускаться будет и на 2.0.

kruzer25

Имхо, расширение базовых классов - совсем некрасиво.
Впрочем, эту задачу я уже в любом случае пишу для 3.5, посмотрим, умеет ли оно с 3.5 работать...

karkar

компилятор C# 3.0 замечательно таргетит 2.0 фреймворк

Правда? Мне казалось там FW2 SP1, который все равно надо ставить, если имеешь просто FW2.0.

Dasar

Мне казалось там FW2 SP1, который все равно надо ставить, если имеешь просто FW2.0.
в sp1 есть серьезные изменения по сравнению с fw2?

bleyman

можно просто добавить в поставку System.Core.
Когда я смотрел, мне показалось, что там есть довольно много стрёмных штук, вроде пайпов.
Поинт-то в использовании второго фреймворка состоит не в том, чтобы избавить юзеров от закачки сотен мегабайт, а в том, что он работает на куче платформ, типа 98 винды и Mono. Просто потыренная System.Core как она есть на Mono просто не запустится в силу наличия вызовов нативных методов, ну и с 98-ой неясно.
Penartur: "Имхо, расширение базовых классов - совсем некрасиво." - лол, расскажи это чувакам из микрософта. Весь Linq состоит из расширения базовых классов.

kruzer25

Поинт-то в использовании второго фреймворка состоит не в том, чтобы избавить юзеров от закачки сотен мегабайт, а в том, что он работает на куче платформ, типа 98 винды и Mono.
Ага, у меня пролблема - именно в этом (правда, х его з, что там на целевом компьютере; 2.0 точно есть, а вот насчёт чего-нибудь выше - хз).

Dasar

Просто потыренная System.Core как она есть на Mono просто не запустится в силу наличия вызовов нативных методов
Если ты эти нативные функции вызывать не будешь, то и работать все будет, в том числе и на моно.

karkar

в sp1 есть серьезные изменения по сравнению с fw2?
Представления не имею. Главное, что если у юзера стоит FW2.0, этого недостаточно для запуска проги, скомпиленной C# 3.0, как я понял.

Dasar

Представления не имею. Главное, что если у юзера стоит FW2.0, этого недостаточно для запуска проги, скомпиленной C# 3.0, как я понял.
а у нас запускается...
если ставить таргет - 2.0 - то вообще без проблем.
если ставить таргет 3.5 - то используемые либы надо тащить с собой, чтобы запускалось на 2.0.
Оставить комментарий
Имя или ник:
Комментарий: