2013-08-19 3 views
-3

У меня есть код устаревшего кода в моем приложении и вы хотите его оптимизировать. arrayOfAttrValue имеет уникальные атрибуты. Можно ли использовать LINQ для оптимизации цикла? Если да, тогда вы можете показать мне, как?Fetch Несколько элементов из linq

foreach (AttrValue attr in arrayOfAttrValue) 
{ 
    switch(attr.Attribute) 
    { 
     case Constants.Gender 
      mymodel.Gender = attr.Value; 
      break; 
     case Constants.Identifier 
      mymodel.AppIdentifier = attr.Value; 
      break; 
    } 
} 

Мое намерение не обязательно использовать только LINQ. Любой другой способ свести к минимуму цикл также поможет.

Спасибо.

+4

LINQ не оптимизирован. LINQ делает более читаемым (или, по крайней мере, более читаемым для определенных лиц) – xanatos

+0

«Оптимизировать» его _how_? –

+2

Какова логика этого кода? Он может присваивать свойства модели несколько раз –

ответ

1

Нет, вы не можете сделать это в «истинном» LINQ, потому что LINQ занимается производством новых объектов из старых объектов. Здесь mymodel является ранее существовавшим объектом, который вы хотите изменить.

Вы можете использовать Array.ForEach или List.ForEach но

  1. Они не «истинный» LINQ и

  2. Полученный код будет эквивалентен (немного медленнее, потому что там будет делегатом)

Тем не менее, вероятно, хотел downvoter некоторые LINQ, так что я дам некоторые LINQ:

arrayOfAttrValue.All(attr => { 
    mymodel.Gender = attr.Attribute == Constants.Gender ? attr.Value : mymodel.Gender; 
    mymodel.AppIdentifier = attr.Attribute == Constants.Identifier ? attr.Value : mymodel.AppIdentifier; 
    return true; 
}); 

Еще одна линия, игнорирующая линии {}.

+3

@Downvoter, можете ли вы добавить ценный бесполезный комментарий? – xanatos

+0

Мое намерение состоит в том, чтобы не использовать только LINQ. Любой другой способ свести к минимуму цикл также поможет мне. –

+0

@Al. Этот код уже минимален ... если у вас нет других проблем (например, одного и того же кода в сотнях разных мест). Его намерения ясны, размер i почти минимально возможный (и, вероятно, минимальный как количество символов), и это самый быстрый. – xanatos

1

У вас есть список атрибутов, представляющих пары ключ-значение. Естественным способом сохранения таких структур данных является словарь. Таким образом, преобразовать формат ввода данных в словарь:

var attributes = arrrayOfAttrValue.ToDictionary(a => a.Attribute, a => a.Value); 

Или, если каждый атрибут не является уникальным в массиве, словарь создание будет сложнее, но это формат данных у вас есть. Для того, чтобы работать с вашими данными проще, вы должны преобразовать их в удобный формат:

var attributes = arrayOfAttrValue 
        .GroupBy(a => a.Attribute)     
        .ToDictionary(g => g.Key, g => g.Select(a => a.Value).Last()); 

После создания словаря атрибутов, вы можете просто проверить, если у вас есть значение атрибута и присвоить это значение для моделирования свойства. Атрибуты извлечения Теперь простым и понятным для любого читателя:

if (attributes.ContainsKey(Constants.Gender)) 
    model.Gender = attributes[Constants.Gender]; 

if (attributes.ContainsKey(Constants.Identifier)) 
    model.AppIdentifier = attributes[Constants.Identifier]; 
+0

@ Downvloter, можете ли вы добавить ценные комментарии? –

+3

+1 @Downvoter Мне тоже спасибо! ах, lazyberezovsky, я скажу, что ваш код является самой раздутой нечитаемой вещью, которую я когда-либо видел за последние 5 минут. Все еще +1, потому что есть намерение :-) Возможно, вы могли бы напрямую использовать 'ToLookup()' – xanatos

+0

@xanatos, который я думал о поиске, но исходная логика использует только последнее значение. О раздутом коде. Это зависит от того, что содержит массив arrayOfAttrValue.Если каждое значение уникально, то создание словаря будет простым: «var attributes = arrrayOfAttrValue.ToDictionary (a => a.Attribute, a => a.Value);« Обновленный код с этим образцом –

-1

Вам не нужно LINQ для этого, потому что это сделает проблему более сложной, просто цикл в норме:

bool gotGender, gotAppIdentifier; 
foreach (AttrValue attr in arrayOfAttrValue.Reverse()) 
{ 
    switch(attr.Attribute) 
    { 
    case Constants.Gender: 
     if(!gotGender){ 
     mymodel.Gender = attr.Value 
     gotGender = true; 
     } 
     break; 
    case Constants.Identifier: 
     if(!gotAppIdentifier){ 
     mymodel.AppIdentifier = attr.Value 
     gotAppItentifier = true; 
     } 
     break; 
    } 
    if(gotGender&&gotAppIdentifier) break; 
} 
+0

Если if/else сделает это более понятным, а лишние переменные будут лишними. –

+0

@GrantThomas Я не знаю, чтобы выразить, почему, но это не избыточно, из-за моих бедных английских словарей. Точка '.Reverse()' (цикл из последнего элемента), а первая влияет на изменение как «Gender», так и «AppIdentifier». «Switch-case» - это всего лишь код OP, если бы я был им, я бы использовал «if», конечно. –

+0

@KingKing на самом деле даже наоборот не поможет здесь, поэтому вы проверяете как пол, так и идентификатор будет установлен. Рассмотрим, являются ли последние три атрибута «id, gender, gender». У вас не будет последнего пола, назначенного здесь –

1

Нет необходимости сделать петлю вручную в коде, вы можете сделать это просто с .LastOrDefault():

mymodel.Gender = arrayOfAttrValue 
    .Where(attr => attr.Attribute == Constants.Gender) 
    .Select(attr => attr.Value).LastOrDefault() ?? mymodel.Gender; 
mymodel.AppIdentifier = arrayOfAttrValue 
    .Where(attr => attr.Attribute == Constants.Identifier) 
    .Select(attr => attr.Value).LastOrDefault() ?? mymodel.AppIdentifier; 

?? mymodel.Gender убеждается мы не ставим его Default(T) (т.е. null) в ситуации, когда в противном случае оно было установлено ранее. Затем это соответствует функциональной логике вашего первоначального вопроса.

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

Если у вас есть проблемы с производительностью это, то вы, вероятно, захотите рассмотреть вопрос об использовании лучшей структуры данных, чем arrayOfAttrValue (что-то, что является индексным доступом к которой Attribute таким как Dictionary<,>).

+0

Кажется, что это работает, но цикл дважды? Похоже, это не очень эффективно. –

+1

Цикл цикла @KingKing не всегда является плохим, каждый цикл работает очень мало, единственные накладные расходы на выполнение цикла два - это то, что вы дважды запускаете счетчик. Однако, поскольку 'arrayOfAttrValue', скорее всего, является' Array', перечислитель будет очень быстрым, так как производительность удара минимальна. Если бы у вас было много свойств, я бы настоятельно предложил словарь и т. Д., Но все равно зависит от того, сколько уникальных значений '.Attribute' есть. Я согласен, что Linq на самом деле не нужен в этом случае, но вопрос был задан для ответа Linq, и это делает логику очень ясной. – Seph