func index(of element: Element) -> Int?
var alphabets = ["A", "B", "E", "D"]
Пример1
let index = alphabets.index(where: {$0 == "A"})
Пример2
if let i = alphabets.index(of: "E") {
alphabets[i] = "C" // i is the index
}
print(alphabets)
// Prints "["A", "B", "C", "D"]"
Вы могли сделать это:
public static Boolean IsEmpty<T>(this IEnumerable<T> source)
{
if (source == null)
return true; // or throw an exception
return !source.Any();
}
Редактирование : Обратите внимание, что просто использование.Count метода будет быстро, если базовый источник на самом деле будет иметь быстрое свойство Count. Допустимая оптимизация выше должна была бы обнаружить несколько базовых типов и просто использовать.Count свойство тех, вместо.Any () подход, но затем отступить к.Any (), если никакая гарантия не может быть сделана.
@Konrad, что удивляет меня, - то, что в моих тестах, я передаю список в метод, который принимает IEnumerable<T>
, таким образом, время выполнения не может оптимизировать его путем называния количества () дополнительным методом для IList<T>
.
я могу только предположить, что количество () дополнительный метод для IEnumerable делает что-то вроде этого:
public static int Count<T>(this IEnumerable<T> list)
{
if (list is IList<T>) return ((IList<T>)list).Count;
int i = 0;
foreach (var t in list) i++;
return i;
}
..., другими словами, немного оптимизации во время выполнения для особого случая IList<T>
.
РЕДАКТИРОВАНИЕ / @Konrad +1 помощник - Вы правы относительно этого более вероятно находиться на ICollection<T>
.
Вторая опция намного более быстра, если у Вас есть несколько объектов.
Any()
возвраты, как только 1 объект найден. Count()
должен продолжать проходить весь список. , Например, предполагают, что перечисление имело 1 000 объектов.
Any()
проверил бы первый, затем возвратил бы true. Count()
возвратился бы 1000 после пересечения всего перечисления. Это потенциально хуже при использовании одного из переопределений предиката - количество () все еще должно проверить каждый объект, даже это там - только одно соответствие.
Вы привыкаете к использованию Любого - это действительно имеет смысл и читаемо.
Один протест - если у Вас есть Список, а не просто IEnumerable затем использует свойство Count того списка.
Я просто описал быстрый тест, попробуйте это:
IEnumerable<Object> myList = new List<Object>();
Stopwatch watch = new Stopwatch();
int x;
watch.Start();
for (var i = 0; i <= 1000000; i++)
{
if (myList.Count() == 0) x = i;
}
watch.Stop();
Stopwatch watch2 = new Stopwatch();
watch2.Start();
for (var i = 0; i <= 1000000; i++)
{
if (!myList.Any()) x = i;
}
watch2.Stop();
Console.WriteLine("myList.Count() = " + watch.ElapsedMilliseconds.ToString());
Console.WriteLine("myList.Any() = " + watch2.ElapsedMilliseconds.ToString());
Console.ReadLine();
второе почти в три раза медленнее :)
Попытка теста секундомера снова со Стеком или массивом или другими сценариями это действительно зависит от типа списка, которым это кажется - потому что они доказывают количество, чтобы быть медленнее.
, Таким образом, я предполагаю, что это зависит от типа списка, который Вы используете!
(Только для указания я поместил 2000 +, объекты в Списке и количестве были еще быстрее, напротив с другими типами)
сам LINQ должен делать некоторую серьезную оптимизацию вокруг количества () метод так или иначе.
это удивляет Вас? Я предполагаю, что для IList
реализации, Count
просто чтения число элементов непосредственно, в то время как Any
должен запросить IEnumerable.GetEnumerator
метод, создают экземпляр и вызов MoveNext
, по крайней мере, однажды.
РЕДАКТИРОВАНИЕ / @Matt:
я могу только предположить, что количество () дополнительный метод для IEnumerable делает что-то вроде этого:
Да, конечно, это делает. Это - то, что я имел в виду. На самом деле это использует ICollection
вместо IList
, но результатом является то же.
Этот метод расширения работает для меня:
public static bool IsEmpty<T>(this IEnumerable<T> enumerable)
{
try
{
enumerable.First();
return false;
}
catch (InvalidOperationException)
{
return true;
}
}
Хорошо, а что насчет этого?
public static bool IsEmpty<T>(this IEnumerable<T> enumerable)
{
return !enumerable.GetEnumerator().MoveNext();
}
РЕДАКТИРОВАТЬ: Я только что понял, что кто-то уже набросал это решение. Было упомянуто, что это сделает метод Any (), но почему бы не сделать это самому? С уважением
Другая идея:
if(enumerable.FirstOrDefault() != null)
Однако мне больше нравится подход Any ().
List.Count
равен O (1) согласно документации Microsoft:
http://msdn.microsoft.com/en-us/library/27b47ht3.aspx
, поэтому просто используйте List.Count == 0
это намного быстрее, чем запрос
Это потому, что у него есть элемент данных с именем Count, который обновляется каждый раз, когда что-то добавляется или удаляется из списка, поэтому, когда вы вызываете List.Count
ему не нужно перебирать каждый элемент, чтобы получить его, он просто возвращает элемент данных.
Я бы сделал одно небольшое дополнение к коду, на котором вы, кажется, остановились: проверьте также ICollection
, так как это реализовано даже некоторыми неустаревшими универсальными классами, такими как хорошо (т. е. Queue
и Stack
). Я бы также использовал as
вместо is
, так как это более идиоматично и , как было показано, быстрее.
public static bool IsEmpty<T>(this IEnumerable<T> list)
{
if (list == null)
{
throw new ArgumentNullException("list");
}
var genericCollection = list as ICollection<T>;
if (genericCollection != null)
{
return genericCollection.Count == 0;
}
var nonGenericCollection = list as ICollection;
if (nonGenericCollection != null)
{
return nonGenericCollection.Count == 0;
}
return !list.Any();
}