Это, по-видимому, один из тех сценариев, в которых Интернет создает множество противоречивой информации.
iter_swap
идентичен swap
, и по этой логике MSDN было бы правильно сказать, что нужно просто придерживаться swap
. swap
является просто возможным реализация iter_swap
, открывающая дверь для возможных оптимизаций в iter_swap
для определенных специализаций, при условии, что сохраняется постоянная гарантия функции. Стандарт, под [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 во многих случаях.
Как другие ответы упоминают, 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);
Я не думаю, что существует способ сделать так непосредственно, но это в значительной степени as good
для использования дополнительного метода, который возвращает новый набор через yield return
ключевое слово. Они могли прибыть из существующей ранее библиотеки; другие указали, что LINQ имеет Reverse
метод, и вещи как OrderBy
также работали бы.
Пример: если Вы будете использовать дополнительный метод LINQ Reverse()
на IEnumerable<T>
, который использует yield return
для предоставления набора в обратном порядке, то выполнение foreach(var myThing in myCollection.Reverse())
перечислит через набор в обратном порядке.
Важный : yield return
является ключевым. Это означает, "когда я перечисляю этот набор, затем пойдите вещи выборки". В противоположность альтернативе для просто построения новый , инвертированный набор, который очень неэффективен и возможно имеет побочные эффекты.
Используя IList<T>
от Библиотека Универсального набора C5 , Обратное повторение является функцией, а не расширением:
foreach (var i in list.Reverse())
{
}
Также, можно использовать Shuffle()
метод для получения случайного упорядочивания:
var listClone = (IList<T>) list.Clone();
listClone.Shuffle();
foreach (var i in listClone)
{
}
С 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];
}
}
}
}
}
Используя 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)
{
}
можно сделать это назад:
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);
}
Вы хотите к рэнду набор и взаимодействуете с ним?
, Если да, попробуйте это:
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>;
От моего чтения Спецификации языка C# foreach оператор цикла зависит от структуры/класса/интерфейса, которая выполняется с помощью итераций, имея GetEnumerator () функция, определяемая на него. Объект, возвращенный GetEnumerator (), должен иметь MoveNext () определенный как функция членства. MoveNext () определяется как доступ к "первому" объекту в списке на его первом вызове, тогда "следующее" на последующих вызовах, возвращая true, пока никакие дальнейшие элементы не существуют в списке, в котором это возвращает false.
функция Domenic относится к, возврат урожая, сначала появляется в 2,0 версиях спецификации и, действительно кажется, полезна с этой целью. Для версии 1.1 Ваша единственная опция состояла бы в том, чтобы получить новую структуру/класс/интерфейс из Вашей базы и переопределить GetEnumerator () для возврата нового IEnumerator, где MoveNext () функция будет следовать различным правилам в выборе первый элемент набора и любой последующий элемент набора.
Моя собственная рекомендация состояла бы в том, чтобы использовать индексируемый набор, затем использовать для цикла с соответствующим индексным вычислением (здесь, можно было использовать генератор случайных чисел при необходимости с целочисленным массивом или некоторой другой техникой для проверки, что то же индексное значение не используется дважды), если необходимо сделать это в фактической практике.
Используйте случайное упорядочивание
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();
Вы могли отсортировать Список путем предоставления собственного Компаратора и выполнить итерации по тому.
Мне на самом деле понравился подход 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);
}
O(N)
по всей стоимости isn' t практичный!
– Larry
8 March 2010 в 15:43