Я часто делаю следующий встречный индексом беспорядок в цикле foreach узнавать, нахожусь ли я на первом элементе или нет. Есть ли более изящный способ сделать это в C#, чем-то вроде if(this.foreach.Pass == 1)
и т.д.?
int index = 0;
foreach (var websitePage in websitePages) {
if(index == 0)
classAttributePart = " class=\"first\"";
sb.AppendLine(String.Format("<li" + classAttributePart + ">" +
"<a href=\"{0}\">{1}</a></li>",
websitePage.GetFileName(), websitePage.Title));
index++;
}
Другой подход - признать, что «некрасивая часть» должна быть где-то реализована, и предоставить абстракцию, которая скрывает «некрасивую часть», чтобы вам не приходилось повторять ее в нескольких местах и можно было сосредоточиться на конкретном алгоритме. . Это можно сделать с помощью лямбда-выражений C # (или с помощью анонимных делегатов C # 2.0, если вы ограничены .NET 2.0):
void ForEachWithFirst<T>(IEnumerable<T> en,
Action<T> firstRun, Action<T> nextRun) {
bool first = true;
foreach(var e in en) {
if (first) { first = false; firstRun(e); } else nextRun(e);
}
}
Теперь вы можете использовать этот многократно используемый метод для реализации своего алгоритма следующим образом:
ForEachWithFirst(websitePages,
(wp => sb.AppendLine(String.Format("<li class=\"first\">" +
"<a href=\"{0}\">{1}</a></li>", wp.GetFileName(), wp.Title)))
(wp => sb.AppendLine(String.Format("<li>" +
"<a href=\"{0}\">{1}</a></li>", wp.GetFileName(), wp.Title))) );
Вы можете разработать абстракция по-разному в зависимости от точного повторяющегося узора. Хорошо то, что - благодаря лямбда-выражению - структура абстракции полностью зависит от вас.
Чуть менее многословно:
string classAttributePart = " class=\"first\"";
foreach (var websitePage in websitePages)
{
sb.AppendLine(String.Format("<li" + classAttributePart + "><a href=\"{0}\">{1}</a></li>", websitePage.GetFileName(), websitePage.Title));
classAttributePart = string.Empty;
}
Если вы используете .NET 3.5, вы можете использовать перегрузку Select, которая дает вам индекс, и проверить это. Тогда вам также не понадобится StringBuilder. Вот код для этого:
string[] s = websitePages.Select((websitePage, i) =>
String.Format("<li{0}><a href=\"{1}\">{2}</a></li>\n",
i == 0 ? " class=\"first\"" : "",
websitePage.GetFileName(),
websitePage.Title)).ToArray();
string result = string.Join("", s);
Он выглядит немного более многословным, но это в основном потому, что я разбил очень длинную строку на несколько более коротких.
Вы можете использовать цикл for
вместо цикла foreach
. В этом случае ваш цикл for мог бы начинать свой индекс с 1, и вы могли бы выполнять первый элемент вне цикла, если длина больше 0.
По крайней мере, в этом случае вы бы не делали дополнительного сравнения на каждой итерации.
if (websitePages.IndexOf(websitePage) == 0)
classAttributePart = " class=\"last\"";
Это может быть более элегантно, но, вероятно, будет менее производительно, поскольку придется проверять индекс каждого элемента.
login _ required
предназначен для обращения к ракурсу, вызываемому, не включающему (), и просмотра исходного кода:
http://code.djangoproject.com/browser/django/tags/releases/1.1.1/django/conf/urls/defaults.py#L9
- Я не думаю, что существует простой способ использования стандартного (или даже пользовательского) login _ обязательного
с include () для достижения желаемого.
Написав это, я думаю, что разумным подходом было бы использовать некоторое «требуемое промежуточное программное обеспечение», как это: http://www.djangosnippets.org/snippets/1179/ и забыть о украшении urls в urls.py.
-121--1229802-Посмотрите на Blackbird . Это экранный javascript-журнал/отладчик. В коде следует поместить log.debug (объект), и он будет выведен в обозреватель в наложении div. Я не знаю, работает ли это, если просто передать объект, но очевидно, что у вас уже есть object.dumpvars () уже отработан.
-121--4667560-Это может быть немного лучше
bool doInit = true;
foreach (var websitePage in websitePages)
{
if (doInit)
{
classAttributePart = " class=\"first\"";
doInit = false;
}
sb.AppendLine(String.Format("<li" + classAttributePart + "><a href=\"{0}\">{1}</a></li>", websitePage.GetFileName(), websitePage.Title));
}
Я в конечном итоге делаю такого рода вещи тоже, и это меня также беспокоит.
Как насчет этого?
var iter = websitePages.GetEnumerator();
iter.MoveNext();
//Do stuff with the first element
do {
var websitePage = iter.Current;
//For each element (including the first)...
} while (iter.MoveNext());
Вы можете сделать это перед циклом foreach, если вы делаете это только для первого индекса.
Если вас интересует только первый элемент, лучший (в смысле наиболее читабельный) способ - использовать LINQ, чтобы узнать, какой элемент является первым. Например, так:
var first = collection.First();
// do something with first element
....
foreach(var item in collection){
// do whatever you need with every element
....
if(item==first){
// and you can still do special processing here provided there are no duplicates
}
}
Если вам нужно числовое значение индекса или непервый индекс, вы всегда можете сделать
foreach (var pair in collection.Select((item,index)=>new{item,index}))
{
// do whatever you need with every element
....
if (pair.index == 5)
{
// special processing for 5-th element. If you need to do this, your design is bad bad bad
}
}
PS И самый лучший способ - использовать for
-петлю. Используйте foreach
только если for
недоступен (т.е. коллекция является IEnumerable
, а не списком или чем-то еще)
Другой подход заключается в использовании первого селектора jQuery для установки класса вместо кода на стороне сервера.
$(document).ready(function(){
$("#yourListId li:first").addClass("first");
}
Как любит говорить мой отец: «Используйте правильный инструмент для работы».
В этом случае посмотрите, что должен делать ваш цикл.
В противном случае, отвечая на ваш вопрос, не может быть простого неполнотного средства для определения индекса элемента списка при доступе к нему в цикле foreach.
ОКОНЧАТЕЛЬНОЕ ОБНОВЛЕНИЕ: Две библиотеки кажутся примерно эквивалентными. Zlib дает примерно на 20% лучшее сжатие, в то время как скорость декодирования LZO примерно в два раза быстрее, но производительность любого из них очень мала, почти ничтожна. Это мой окончательный ответ. Спасибо за все остальные ответы и комментарии!
ОБНОВЛЕНИЕ: После внедрения сжатия LZO и заметного улучшения производительности, очевидно, что в ударе по производительности виноват мой собственный код (возможно значительное увеличение количества сценариев на пакет, таким образом, мой эффект «интерпретатор» становится намного больше.) Я хотел бы смиренно извиниться за то, что взбесился переложить вину, и я надеюсь, что никаких обид не будет. Я сделаю некоторые профилирование, и тогда, возможно, я смогу получить некоторые цифры, которые будут более полезны для кого-то еще.
ORIGINAL POST:
Хорошо, я наконец-то начал писать код для этого. Я начал со Злиба, вот первые мои выводы.
Сжатие Злиба безумно велико. Это надежно сокращает пакеты, скажем, 8,5 kib до, скажем, 750 байт или менее, даже при сжатии с Z_BEST_SPEED (вместо Z_DEFAULT_COMPRESSION.) Время сжатия также довольно хорошее.
Однако я понятия не имел, что скорость декомпрессии чего-либо может быть даже таким плохим. У меня нет фактических чисел, но это должно занять хотя бы 1/8 секунды на пакет! (Core2Duo T550 при 1,83 ГГц.) Совершенно неприемлемо.
Из того, что я слышал, LZMA является компромиссом худшей производительности по сравнению с лучшим сжатием по сравнению с Zlib. Поскольку сжатие Zlib уже перегружено, а его производительность уже невероятно плоха, LZMA скрывается от невидимого пока вида.
Если время декомпрессии LZO такое же хорошее, как утверждается, то это то, что я буду использовать. Я думаю, что в конце концов сервер все еще сможет отправлять пакеты Zlib в крайних случаях, но клиенты могут быть настроены игнорировать их и это будет по умолчанию.
-121--4349330-Если вы читаете такое выражение
if ('string1') or ('string2') or ('string3' in line):
Проблема становится очевидной. Что произойдет, так это то, что «string1» вычисляется как True, так что остальное выражение является коротким.
Длинная рука, чтобы написать это это
if 'string1' in line or 'string2' in line or 'string3' in line:
Который является бит повторяется, так что в этом случае лучше использовать любой ()
, как в ответ Игнасио
В этом примере можно избавиться от проверки индекса таким образом.
foreach (var websitePage in websitePages)
{
classAttributePart = classAttributePart ?? " class=\"first\"";
sb.AppendLine(String.Format("<li" + classAttributePart + "><a href=\"{0}\">{1}</a></li>", websitePage.GetFileName(), websitePage.Title));
}
Для выполнения такого рода задач лучше проверить результирующую переменную данных. В этом случае он проверяет значение null строки classAttriburePart и добавляет начальное значение.
public static class ExtenstionMethods
{
public static IEnumerable<KeyValuePair<Int32, T>> Indexed<T>(this IEnumerable<T> collection)
{
Int32 index = 0;
foreach (var value in collection)
{
yield return new KeyValuePair<Int32, T>(index, value);
++index;
}
}
}
foreach (var iter in websitePages.Indexed())
{
var websitePage = iter.Value;
if(iter.Key == 0) classAttributePart = " class=\"first\"";
sb.AppendLine(String.Format("<li" + classAttributePart + "><a href=\"{0}\">{1}</a></li>", websitePage.GetFileName(), websitePage.Title));
}