10:16 AM
0
Q: Как конвертировать IEnumerable в массив?

James BondВыполняю учебную задачу по поиску кратчайшего маршрута для обхода списка чекпоинтов роботом-пылесосом)) Нужно написать класс, основной метод которого при помощи пары вспомогательных переберет все возможные варианты маршрутов, оценит расстояния и вернет лучший найденный маршрут. Как я не ломал гол...

 
Если у вас есть метод с yield return, то использовать всякие .To..() - это глупость, ибо тем самым вы нарушаете всю суть yield, а именно "ленивость" (что такое yield отлично описано в этом ответе).
 
@EvgeniyZ Ну может быть такое, что просто удобно генерить что-то через рекурсию или ещё как-то хитро, с использованием yield и тогда смысл тут будет в удобстве, а не в ленивости. И с результатом можно делать что угодно. Хотят в результате массив - это нормально.
Покажите ваш код. И по идее .ToArray() должен работать, не вижу препятствий. В свежих версиях C# ему и тип не нужно указывать, он его возьмёт из IEnumerable<T>.
 
@CrazyElf Извините, не могу себе такое представить, из-за чего не вижу смысла даже в случае с рекурсией использовать yield и условный .ToList() вместе, ибо второй заставит "прогрузить" все данные разом, что убивает весь смысл первого. С таким успехом проще уж делать обычную коллекцию "result" и ее возвращать в конце рекурсии... Вот в случаях когда нужны данные здесь и сейчас, без ленивости (например взять из базы через EF и сделать .ToList()), порой да, это полезно, но реализовывать "ленивый" метод ради того, чтоб потом игнорировать всю ленивость... Ну не знаю, как по мне, это странно)
 
@EvgeniyZ Ну не знаю, я лично не люблю такой код, где в начале создаётся список, а потом то там то сям делается .Add в него. По мне так yield выглядит красивее. А дальше хочешь используй и дальше ленивый вариант, хочешь превращай в список или массив.
 
Смысл yield return для меня в данном случае в том, что с ним я смогу получать одну перестановку (вариант маршрута) за раз, а без него придется заводить дополнительную матрицу и складывать промежуточные варианты маршрутов в неё. Тоже вариант, но не так изящно. А массив нужен потому, что все методы из класса, в котором я работаю, возвращают массивы, другие классы, вызывающие эти методы, ожидают массивы, и так далее. Что лучше - переделывать весь проект (который после этого ещё и не примут), или один раз применить .ToArray()?
@EvgeniyZ, ToArray можно применить не в самом методе, генерирующем перестановки, а в вызывающем - это всего лишь детали.
 
10:16 AM
Где вызывается - сказанного мной выше не отменяет. В любом случае, как правильно подметили выше, проблем вызвать нужную вам конвертацию быть не должно, показывайте код если считаете иначе.
 
Уважаемый EvgeniyZ, я не сомневаюсь, что конвертация вызывается без проблем. Я прошу только показать как это выглядит на реальном коде, с краткими комментариями что есть что, не более. Всё это уложится в пару предложений. Код показать не могу, потому что его нет - есть куча набросков в разных файлах. А по поводу "сказанного мной выше не отменяет" - было бы интересно узнать, почему. Метод возвращает промежуточный результат рассчетов - что с этим результатом будет происходить дальше, разве как-то касается этого метода? По идее не должно... А при следующем вызове генерация просто продолжится.
 
Странный вы вопрос задаете, раз как минимум 2 человека посчитали, что у вас есть код, к которому не можете применить .ToArray(), зачем тогда "для IEnumerable используется какая-то незнакомая мне перегрузка этого метода" мне непонятно... Ну ладно, вот вам код. "узнать, почему" - про это я сказал выше, я считаю странным делать "ленивый" метод и не использовать его по максимуму. Я могу понять это решение, если у вас в одном места также "лениво" читаются данные, а в другом вы берете сразу, но делать "ленивый" метод лишь чтоб вызывать .ToArray(), ну такое)
 
А, так вот чего Вы не могли понять...)) Судя по всему Вы решили, что я хочу упаковывать в массив результаты метода, возвращенные через yield return по одному. В общем, логика совершенно другая. Метод с yield return будет возвращать коллекцию, а не отдельные значения. Нюанс в том, что таких коллекций до полного прекращения своей работы он должен сгенерировать несколько десятков, а то и сотен (смотря сколько будет чекпоинтов). Поэтому я и хотел возвращать их не все разом, а по одной.
Добавил скрин - к коду особо не присматривайтесь, это наброски. Главное то, что при применении метода ToArray как Вы показали (да как я и сам пытался делать) откуда-то всплывает массив массивов, и сообщение о невозможности неявного преобразования. Если же изменить возвращаемое значение метода MakeTrivialPermutation с IEnumerable<int[]> на IEnumerable<int>, то жалуется уже на то, что не удается преобразовать int в int[]. В общем, я не понимаю как это должно работать
 
Ну так очевидно вы будете получать массив массивов, ибо вы сами пишете IEnumerable<int[]> (коллекция состоящая из массивов int типа). Почему с IEnumerable<int> у вас пишет "не удается преобразовать" - опять-же, внимание на код, вы делаете yield return array (пытаетесь вернуть массив, когда должны вернуть 1 объект). Тут нет ничего сверхъестественного, IEnumerable - это обобщение "коллекции", а yield - это возврат одного объекта данной коллекции.
 
Теперь понял, спасибо! Блин, как же извратиться...)) Не массив массивов же использовать
 
10:16 AM
На будущее, пожалуйста, если вас просят код, прикладывайте его. Нам не обязательно знать что у вас там за логика, нам важно лишь понимать что вы от нас просите, не более. Вот вы попросили от меня пример, я предоставил, один метод с одной строкой кода, вам понятно что там? Да. Вот аналогичное просят и от вас, просто минимальный пример, который воспроизведет вашу проблему. А то смотрите, только спустя 3 часа мы вдруг выясняем, что у вас IEnumerable<int[]> и проблема вовсе не связана с неким "особенным" .ToArray()... Также картинки кода - это плохо, вставьте текстом, аналогично и ошибку.
 
Хорошо, учту. Просто обычно когда прикладываешь код все начинают обсуждать именно его, забывая о самом вопросе. Поэтому я старался этого не делать.
 
Может просто using System.Linq; забыл?
 
Нет, не забыл. С этим не связано...
 
bestOrder должен иметь тип int[][], а не int[].
 
@Qwer Советую вникнуть в вопрос, прочитать комментарии, а затем писать свои догадки. Сейчас вы тычете пальцем в небо, не пытаясь даже вникнуть в то, что происходит...
 
10:16 AM
@EvgeniyZ Человек хочет массив, он его получил. Проблема решена. Нашего мнения относительно реализации алгоритма он не спрашивал.
 
@Qwer, bestOrder должен иметь тот тип, который ему назначен, и инициализировать его нужно тем значением, которое под этот тип подходит, а не наоборот)) В этом и заключалась суть проблемы.