Это могло бы сделать это:
function parseItem (item) {
const [, stringPart = '', numberPart = 0] = /(^[a-zA-Z]*)(\d*)$/.exec(item) || [];
return [stringPart, numberPart];
}
function sort (array) {
return array.sort((a, b) => {
const [stringA, numberA] = parseItem(a);
const [stringB, numberB] = parseItem(b);
const comparison = stringA.localeCompare(stringB);
return comparison === 0 ? Number(numberA) - Number(numberB) : comparison;
});
}
console.log(sort(['A1', 'A10', 'A11', 'A12', 'A2', 'A3', 'A4', 'B10', 'B2', 'F1', 'F12', 'F3']))
Если можно использовать LINQ, можно использовать:
var e = enumerable.First();
Это выдаст исключение, хотя, если счетный пусто: в этом случае можно использовать:
var e = enumerable.FirstOrDefault();
FirstOrDefault()
возвратится default(T)
, если счетное будет пусто, который будет null
для ссылочных типов или 'нулевого значения' по умолчанию для типов значения.
, Если Вы не можете использовать LINQ, затем Ваш подход технически корректен и не отличается, чем создание перечислителя с помощью GetEnumerator
, и MoveNext
методы для получения первого результата (этот пример принимает счетный, IEnumerable<Elem>
):
Elem e = myDefault;
using (IEnumerator<Elem> enumer = enumerable.GetEnumerator()) {
if (enumer.MoveNext()) e = enumer.Current;
}
Joel Coehoorn упомянул .Single()
в комментариях; это будет также работать, если Вы будете ожидать, что Ваше счетное будет содержать точно один элемент, то - однако он выдаст исключение, если это будет или пустым или больше, чем один элемент. Существует соответствие SingleOrDefault()
метод, который касается этого сценария подобным способом к [1 111]. Однако David B объясняет, что SingleOrDefault()
может все еще выдать исключение в случае, где счетное содержит больше чем один объект.
Редактирование: Спасибо Marc Gravell для указания, что я должен избавиться от моего IEnumerator
объект после использования его - я отредактировал non-LINQ пример для отображения using
ключевое слово для реализации этого шаблона.
На всякий случай Вы используете.NET 2.0 и не имеете доступа к LINQ:
static T First<T>(IEnumerable<T> items)
{
using(IEnumerator<T> iter = items.GetEnumerator())
{
iter.MoveNext();
return iter.Current;
}
}
Это должно сделать то, что Вы ищете..., это использует дженерики так Вы для получения первого объекта на любом типе IEnumerable.
Вызов это как так:
List<string> items = new List<string>() { "A", "B", "C", "D", "E" };
string firstItem = First<string>(items);
Или
int[] items = new int[] { 1, 2, 3, 4, 5 };
int firstItem = First<int>(items);
Вы могли изменить его с готовностью достаточно для имитации.NET 3.5's IEnumerable. ElementAt () дополнительный метод:
static T ElementAt<T>(IEnumerable<T> items, int index)
{
using(IEnumerator<T> iter = items.GetEnumerator())
{
for (int i = 0; i <= index; i++, iter.MoveNext()) ;
return iter.Current;
}
}
Вызов его как так:
int[] items = { 1, 2, 3, 4, 5 };
int elemIdx = 3;
int item = ElementAt<int>(items, elemIdx);
, Конечно, если Вы делаете , имеют доступ к LINQ, затем уже существует много хороших ответов, отправленных...
Ну, Вы не указывали, какую версию .NET Вы используете.
Принятие Вы имеете 3.5, иначе метод ElementAt:
var e = enumerable.ElementAt(0);
Elem e = enumerable.FirstOrDefault();
//do something with e
Используйте FirstOrDefault или цикл foreach, как уже упомянуто. Вручную выборки перечислителя и вызова Текущего нужно избежать. foreach расположит Ваш перечислитель для Вас, если он реализует IDisposable. При вызове MoveNext и Текущий необходимо расположить его вручную (если применимый).