Можете ли вы перечислить коллекцию в C # не по порядку?

Это, по-видимому, один из тех сценариев, в которых Интернет создает множество противоречивой информации.

Стандарт, под [C++11: 25.3.3/5], говорит только, что iter_swap(a,b) имеет результат swap(*a,*b) (и требует, чтобы «a и b были разысканы» и что «*a заменяется с *b»), что на первый взгляд, коррелируют с интерпретацией MSDN.

Однако я полагаю, что Microsoft пренебрегла рассмотрением правила as-if, которое должно позволить реализации сделать iter_swap быстрее, чем swap в некоторых случаях (например, элементы связанного списка).

Поэтому я надеюсь, что цитата comp.std.c++ будет более технически точна из двух.

При этом существует довольно строгий предел оптимизации, которая может быть выполнена. Рассмотрим, например, реализацию iter_swap по связанным элементам списка, которая просто повторно связывает узлы, а не физически меняет значения элементов & mdash; это not действительная реализация, потому что нарушено [наблюдаемое поведение iter_swap наблюдаемого поведения swap.

Поэтому я бы предположил, что в практика может быть мало, если есть какая-либо польза для предпочтения iter_swap по сравнению с swap, и я бы рекомендовал придерживаться последнего для простоты и последовательности. В любом случае семантика перемещения C ++ 11 должна делать swap cinch во многих случаях.

13
задан swilliams 31 October 2008 в 19:25
поделиться

11 ответов

Как другие ответы упоминают, Reverse(), дополнительный метод позволит Вам перечислить последовательность в обратном порядке.

Вот случайный метод расширения перечисления:

public static IEnumerable<T> OrderRandomly<T>(this IEnumerable<T> sequence)
{
    Random random = new Random();
    List<T> copy = sequence.ToList();

    while (copy.Count > 0)
    {
        int index = random.Next(copy.Count);
        yield return copy[index];
        copy.RemoveAt(index);
    }
}

Ваше использование было бы:

foreach (int n in Enumerable.Range(1, 10).OrderRandomly())
    Console.WriteLine(n);
15
ответ дан Jacob Carpenter 31 October 2008 в 19:25
поделиться
  • 1
    Я вижу Вашу точку. Но автор didn' t говорят что-либо о связанных из элементов в массиве, поэтому если Вы предполагаете, что их диапазон связывается, это совпадает со связанной длиной. – pajton 8 March 2010 в 16:03

Я не думаю, что существует способ сделать так непосредственно, но это в значительной степени as good для использования дополнительного метода, который возвращает новый набор через yield return ключевое слово. Они могли прибыть из существующей ранее библиотеки; другие указали, что LINQ имеет Reverse метод, и вещи как OrderBy также работали бы.

Пример: если Вы будете использовать дополнительный метод LINQ Reverse() на IEnumerable<T>, который использует yield return для предоставления набора в обратном порядке, то выполнение foreach(var myThing in myCollection.Reverse()) перечислит через набор в обратном порядке.

Важный : yield return является ключевым. Это означает, "когда я перечисляю этот набор, затем пойдите вещи выборки". В противоположность альтернативе для просто построения новый , инвертированный набор, который очень неэффективен и возможно имеет побочные эффекты.

1
ответ дан Domenic 31 October 2008 в 19:25
поделиться
  • 1
    Действительно сопоставимый @pajton:not. You' ре, говорящее о пределе на размер обрабатываемого массива. I' m говорящий о пределе на диапазон объектов В массиве, независимо от его размера. – Jerry Coffin 8 March 2010 в 15:47

Используя IList<T> от Библиотека Универсального набора C5 , Обратное повторение является функцией, а не расширением:

foreach (var i in list.Reverse())
{
}

Также, можно использовать Shuffle() метод для получения случайного упорядочивания:

var listClone = (IList<T>) list.Clone();
listClone.Shuffle();
foreach (var i in listClone)
{
}
1
ответ дан Marcus Griep 31 October 2008 в 19:25
поделиться
  • 1
    Я не соглашаюсь с Вами. Таким образом, все алгоритмы, работающие в O (n), были бы постоянными, потому что, если у Вас есть массив размера n, но Вы знаете, n выражается как целое число, это имеет меньше, чем элементы MAX_INT, поэтому постоянные. – pajton 8 March 2010 в 15:42

С C# 2.0 у Вас есть способность использовать ключевое слово урожая для реализации пользовательских действительно легких итераторов. Можно читать больше о ключевом слове урожая в MSDN http://msdn.microsoft.com/en-us/library/9k7k7cf0.aspx

, можно думать об урожае как о способности возвратить значение из цикла, но необходимо обратиться к ссылке выше для полного объяснения того, что они и что они могут сделать.

я записал короткий пример о том, как реализовать несколько пользовательских итераторов. Я реализовал их как дополнительные методы ( http://msdn.microsoft.com/en-us/library/bb383977.aspx ) для создания кода более упрощенным, и я также использую инициализаторы массива ( http://msdn.microsoft.com/en-us/library/aa664573.aspx ) для устанавливания начальных значений для списка целых чисел.

Ни дополнительные методы, ни инициализаторы массива не необходимы для реализации пользовательских итераторов, но они - хорошие функции c# 3.0, который помогает записать, что более чистый код

Вот является моими примерами. Это показывает, как выполнить итерации по списку целых чисел, только возвратив Нечетные числа, Четные числа, числа в обратном или completly случайным способом.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            List<int> ints = 
                new List<int> { 1,2,3,4,5,6,7,8,9,10};

            Console.WriteLine("Iterating over Odd numbers only.");
            foreach (int i in ints.Odd())
            {
                Console.WriteLine(i);
            }

            Console.WriteLine("Iterating over Even numbers only.");
            foreach (int i in ints.Even())
            {
                Console.WriteLine(i);
            }

            Console.WriteLine("Iterating over the list in reversed order.");
            foreach (int i in ints.Reversed())
            {
                Console.WriteLine(i);
            }

            Console.WriteLine("Iterating over the list in random order.");
            foreach (int i in ints.Random())
            {
                Console.WriteLine(i);
            }

            Console.ReadLine();
        }
    }

    public static class ListExtensions
    {
        /// <summary>
        /// Iterates over the list only returns even numbers
        /// </summary>
        /// <param name="list"></param>
        public static IEnumerable<int> Even(this List<int> list)
        {
            foreach (var i in list)
            {
                if (i % 2 == 0)
                 {
                    yield return i;
                }
           }
        }

        /// <summary>
        /// Iterates over the list only returns odd numbers
        /// </summary>
        public static IEnumerable<int> Odd(this List<int> list)
        {
            foreach (var i in list)
            {
                if (i % 2 != 0)
                {
                    yield return i;
                }
            }
        }

        /// <summary>
        /// Iterates over the list in reversed order
        /// </summary>
        public static IEnumerable<int> Reversed(this List<int> list)
        {
            for (int i = list.Count; i >= 0; i--)
            {
                yield return i;
            }
        }

        /// <summary>
        /// Iterates over the list in random order
        /// </summary>
        public static IEnumerable<int> Random(this List<int> list)
        {
            // Initialize a random number generator with a seed.
            System.Random rnd =
                new Random((int)DateTime.Now.Ticks);

            // Create a list to keep track of which indexes we've
            // already returned
            List<int> visited =
                new List<int>();

            // loop until we've returned the value of all indexes
            // in the list
            while (visited.Count < list.Count)
            {
                int index =
                    rnd.Next(0, list.Count);

                // Make sure we've not returned it already
                if (!visited.Contains(index))
                {
                    visited.Add(index);
                    yield return list[index];
                }
            }
        }
    }
}
1
ответ дан RenniePet 31 October 2008 в 19:25
поделиться
  • 1
    @pajton, не уделяя внимания стоимости дополнительного пространства, Ваше решение является все еще неправильным. Возьмите следующее в качестве примера: < 1 1 3 3> < 1 3 3 3> Можете Вы говорить they' ре то же? – meta 9 March 2010 в 04:14

Используя System.Linq Вы могли сделать...

// List<...> list;
foreach (var i in list.Reverse())
{
}

Для произвольного порядка необходимо было бы отсортировать его случайным образом использование list.OrderBy (другое расширение Linq) и затем выполнить итерации того заказанного списка.

var rnd = new Random();
var randomlyOrdered = list.OrderBy(i => rnd.Next());
foreach (var i in randomlyOrdered)
{
}
15
ответ дан cfeduke 31 October 2008 в 19:25
поделиться
  • 1
    @Pajton Рассматривают ответ, который дал KennyTM. Это связывает с O (n) вид основания, который только работает, если диапазон целых чисел ограничен. Иначе сортировка не может работать в O (n) – Christopher Oezbek 8 March 2010 в 15:47

можно сделать это назад:

for (int i=col.count-1; i>0; i--){ 
      DoSomething ( col.item[i]) ;
}

Не уверенный в точном синтаксисе, но это - парадигма.

Что касается абсолютно произвольного порядка, можно получить доступ к элементу набора через, он - индекс. Для обеспечения Вы поражаете каждый объект, необходимо было бы отслеживать, которых элементов Вы уже обработали (вероятно, путем копирования набора и затем удаления элемента после доступа).

РЕДАКТИРОВАНИЕ: Больше деталей для произвольного доступа код для произвольного доступа могло выглядеть примерно так:

 collection c = originalCollection;
 while (c.count > 0) {
     int i = randomNumber(seed) mod c.count
     element d = c[i];
     c.remove(d);
     DoSomething(d);
}
0
ответ дан Stephen Wrighton 31 October 2008 в 19:25
поделиться
  • 1
    @Jerry, @pajton, you' ll нужен O (n) в любой случай, если все значения в массиве отличаются. Когда Вы добавляете элемент к таблице, Вы имеете к , хранят точное значение you' ve добавляется (для будущих сравнений). Это будет любой новый объект в списке (для списков блока), или требование для имения, по крайней мере, n блоков (открытое обращение). Это O (n). – P Shved 8 March 2010 в 16:24

Вы хотите к рэнду набор и взаимодействуете с ним?

, Если да, попробуйте это:

Random rand = new Random(Environment.TickCount);

test.Sort((string v1, string v2) => {
                if (v1.Equals(v2))
                {
                    return 0;
                }

                int x = rand.Next();
                int y = rand.Next();

                if (x == y)
                {
                    return 0;
                }
                else if (x > y)
                {
                    return 1;
                }

                return -1; 
            });

for (string item in test)
{
  Console.WriteLn(item);
}
// Note that test is List<string>;
0
ответ дан Zote 31 October 2008 в 19:25
поделиться
  • 1
    @Pavel:no, Вы don' t нужен O (n). O (n) был бы этим, если бы массивы были удвоены в размере (например), you' d ожидают хэш-таблицу к также (приблизительно) дважды в размере. That' s не случай вообще. – Jerry Coffin 8 March 2010 в 15:54

От моего чтения Спецификации языка C# foreach оператор цикла зависит от структуры/класса/интерфейса, которая выполняется с помощью итераций, имея GetEnumerator () функция, определяемая на него. Объект, возвращенный GetEnumerator (), должен иметь MoveNext () определенный как функция членства. MoveNext () определяется как доступ к "первому" объекту в списке на его первом вызове, тогда "следующее" на последующих вызовах, возвращая true, пока никакие дальнейшие элементы не существуют в списке, в котором это возвращает false.

функция Domenic относится к, возврат урожая, сначала появляется в 2,0 версиях спецификации и, действительно кажется, полезна с этой целью. Для версии 1.1 Ваша единственная опция состояла бы в том, чтобы получить новую структуру/класс/интерфейс из Вашей базы и переопределить GetEnumerator () для возврата нового IEnumerator, где MoveNext () функция будет следовать различным правилам в выборе первый элемент набора и любой последующий элемент набора.

Моя собственная рекомендация состояла бы в том, чтобы использовать индексируемый набор, затем использовать для цикла с соответствующим индексным вычислением (здесь, можно было использовать генератор случайных чисел при необходимости с целочисленным массивом или некоторой другой техникой для проверки, что то же индексное значение не используется дважды), если необходимо сделать это в фактической практике.

0
ответ дан 31 October 2008 в 19:25
поделиться
  • 1
    " Вставьте все элементы от первого массива в hashtable" Вам нужен O (n) память для выделения хэш-таблицы, в то время как Вам только дают O (1). – P Shved 8 March 2010 в 15:41

Используйте случайное упорядочивание
http://www.dailycoding.com/..using_linq.aspx

List<Employee> list = new List<Employee>();

list.Add(new Employee { Id = 1, Name = "Davolio Nancy" });
list.Add(new Employee { Id = 2, Name = "Fuller Andrew" });
list.Add(new Employee { Id = 3, Name = "Leverling Janet" });
list.Add(new Employee { Id = 4, Name = "Peacock Margaret" });
list.Add(new Employee { Id = 5, Name = "Buchanan Steven" });
list.Add(new Employee { Id = 6, Name = "Suyama Michael" });
list.Add(new Employee { Id = 7, Name = "King Robert" });
list.Add(new Employee { Id = 8, Name = "Callahan Laura" });
list.Add(new Employee { Id = 9, Name = "Dodsworth Anne" });

list = list.OrderBy(emp => Guid.NewGuid()).ToList();
0
ответ дан Ramesh Soni 31 October 2008 в 19:25
поделиться
  • 1
    Я соглашаюсь без диапазона целого числа, эта проблема не разрешима в O (n) время и постоянное пространство. – faisal 21 April 2013 в 06:48

Вы могли отсортировать Список путем предоставления собственного Компаратора и выполнить итерации по тому.

0
ответ дан Tigraine 31 October 2008 в 19:25
поделиться
  • 1
    Ваш код не работает правильно на [1,2,4] [2,3,2] – Victor Hurdugaci 8 March 2010 в 17:48

Мне на самом деле понравился подход cfeduke с LINQ, и это прослушивает меня, что это выскочило из головы. Добавить к моему предыдущему примеру. Если Вы хотите сделать Четные и нечетные повторения с помощью LINQ, можно использовать

// Even
foreach (var i in ints.FindAll(number => number % 2 == 0))
{
      Console.WriteLine(i);
}

// Odd
foreach (var i in ints.FindAll(number => number % 2 != 0))
{
      Console.WriteLine(i);
}
1
ответ дан TheCodeJunkie 31 October 2008 в 19:25
поделиться
  • 1
    It' s, что делает эти вопросы об интервью академическими, иногда. O(N) по всей стоимости isn' t практичный! – Larry 8 March 2010 в 15:43
Другие вопросы по тегам:

Похожие вопросы: