Ответ 1
Простой трюк: быстрый способ генерации последовательности случайных чисел:
var randomNumbers = Enumerable.Repeat(new Random(), 10).Select(r => r.Next());
Я знаю, что это очень субъективный вопрос (и тот, который может видеть шквал голосов "закрыть его" ), поэтому указывая его на CW и добавляя отказ от ответственности.
Во всяком случае, я работал над проектом в asp.net mvc, используя дозвуковой и внезапно (снова) пораженный элегантностью и "проницательностью" реализации linq, которая лежит на вершине как дозвукового, так и общего linq до библиотеки объектов. Это заставило меня немного приблизиться к моему коду и заставило меня понять, что некоторые из задач, которые я использовал linq для, будут бесконечно сложными (или "почти невозможными" - субъективными, конечно), если их попытают традиционным образом (это, конечно, вполне может быть ограничением во мне).
В любом случае, в результате этого я подумал, что было бы интересно посмотреть, с какими проблемами столкнулись люди, которые были изящно решены с помощью linq.
Чтобы начать, один сценарий, который я недавно использовал, имел объект, на котором было общее свойство "unitid". я хотел иметь возможность группировать набор из них, чтобы манипулировать и исследовать этот набор, когда он разбивается на соответствующие "унифицированные" группы. После долгих раздумий я подошел к этому простому маленькому линейному слою:
// the base collection of the objects - not grouped in any way
IQueryable<ShareholderRSP> rsps = validshareholderPounds
.Where(x => x.Balance > 0)
.OrderBy(x => x.RequestYear);
// the one-liner in question to group the objects by unitid
IList<IGrouping<string, ShareholderRSP>> groupedRSP =
rsps.ToList().GroupBy(t => t.UnitID.ToString()).ToList();
который затем я мог использовать как:
foreach (var rspGrpItem in groupedRSP)
{
foreach (var shareholderRSP in rspGrpItem)
{
// note, i could have also iterated this list too
// which is a base object contained within the collection
// underneath the group collection item
}
// create a top level summary grouped by unitid
// usedPounds is a variable created earlier on in the piece
bookingConfirm.RSPUnitSelect.Add(
new BookingConfirmRSPSelect
{
TotalBeforeUse = rspGrpItem.Sum(rsp => rsp.Balance),
TotalAfterUse = rspGrpItem.Sum(rsp => rsp.Balance) - usedPounds,
UnitNo = rspGrpItem.Key
}
);
}
Если бы я попытался сделать это традиционным способом, моя логика (на мой взгляд) была бы более громоздкой и менее способной адаптироваться к любым изменениям в базовой объектной модели.
Надеюсь, если это не совсем дискуссия, это подчеркнуло мою "радость" при использовании linq.
Все самое лучшее - надеюсь, что упущение объектной модели, о которой идет речь выше, не умаляет цели примера, поскольку, надеюсь, намерение раскрывает все.
Глядя на некоторые прекрасные примеры.
джим
Простой трюк: быстрый способ генерации последовательности случайных чисел:
var randomNumbers = Enumerable.Repeat(new Random(), 10).Select(r => r.Next());
Проект Euler проблема 8 - Найдите наибольший продукт из пяти последовательных цифр в 1000-значном номере. Я решил вчера использовать Linq и Lambda
//orgStr - string variable holding 1000 digit number
var max= Enumerable.Range(0, orgStr.Length - 5).Select(idx =>
{
return orgStr.Substring(idx, 5).Select(x => Int64.Parse(x.ToString()))
.ToArray().Aggregate((a, b) => a * b);
}).ToArray().Max();
Его довольно объяснительный я думаю
Чтобы вычислить объединение коллекции прямоугольников:
var union = rects.Aggregate(Rectangle.Empty, Rectangle.Union);
Часто вы просто используете оператор foreach
или какой-то linq, но внутри него вам нужно дополнительно к самому элементу индекс. Для этого существует перегрузка select-statement.
var itemsWithIndex = myList.Select((item, index) => new { Item = item, Index = index });
foreach(var element in itemsWithIndex)
{
Console.WriteLine("{0,-2} {1}", element.Index, element.Item.ToString());
}
Прекрасная маленькая функция поворота найдена здесь: http://www.extensionmethod.net/Details.aspx?ID=147
public static Dictionary<TKey1, Dictionary<TKey2, TValue>> Pivot<TSource, TKey1, TKey2, TValue>
(
this IEnumerable<TSource> source,
Func<TSource, TKey1> key1Selector,
Func<TSource, TKey2> key2Selector,
Func<IEnumerable<TSource>, TValue> aggregate
)
{
return source.GroupBy(key1Selector).Select(
x => new
{
X = x.Key,
Y = x.GroupBy(key2Selector).Select(
z => new
{
Z = z.Key,
V = aggregate(z)
}
).ToDictionary(e => e.Z, o => o.V)
}
).ToDictionary(e => e.X, o => o.Y);
}
использование:
var result = items.Pivot(s => s.SeasonID,
s => s.FundPropertyEntity.PropertyEntity.PropertyName,
lst => lst.Count());
ошеломляющая...
Я слишком устал проверять нули:
var name = user.NoNull(x => x.Company)
.NoNull(x => x.ParentCompany)
.NoNull(x => x.Name, "N/A");
Я думаю, что метод расширения очевиден. Далее идет еще один метод расширения:
var total = user.NoNull(x => x.Company)
.DefaultForNull(x => x.Users)
.SelectMany(x => x.Email)
.Where(x => x.EndsWith("@gmail.com"))
.Count();
Теперь попробуйте сделать все это без такого метода расширения, предполагая, что любой объект в цепочке может быть NULL:)
Источник для тех, кто спрашивает:)
public static TResult NoNull<TObject, TResult>(this TObject obj, Func<TObject, TResult> accessor, TResult defaultingTo = default(TResult)) {
if (ReferenceEquals(obj, null))
return defaultingTo;
return accessor.Invoke(obj);
}
public static IEnumerable<TResult> DefaultForNull<TObject, TResult>(this TObject obj, Func<TObject, IEnumerable<TResult>> accessor, IEnumerable<TResult> defaultingTo = null) {
if (ReferenceEquals(obj, null))
return defaultingTo ?? Enumerable.Empty<TResult>();
return accessor.Invoke(obj);
}
Это вспомогательный класс для построения строки запроса на основе коллекции параметров. Я поразился, как легко построить его в одном компактном выражении Linq. Когда я написал эту строку, я сразу же подключился к Linq!
public class Parameters : System.Collections.Generic.Dictionary<string, object>
{
private string UrlEncode(object s)
{
return System.Web.HttpUtility.UrlEncode(s.ToString());
}
public override string ToString()
{
return string.Join("&", Keys.Select(k => string.Format("{0}={1}", k, UrlEncode(this[k]))));
}
}
отвечал на вопрос re Array.IndexOf() здесь на SO и "искажал" это вместе:):
.net мы бы "могли" сделать это обычно:
string[] testArray = { "cat", "dog", "banana", "orange" };
var indexOffset = Array.IndexOf(testArray, "banana");
"академическая" альтернатива в linq может быть:
string[] testArray = { "cat", "dog", "banana", "orange" };
var firstItem = testArray.Select((item, index) => new
{
ItemName = item,
Position = index
}).Where(i => i.ItemName == "banana")
.First()
.Position;
Не уверен, какие штрафы за производительность мы увидим здесь, но еще один способ обмануть кошку (или собаку или банан)
джим
еще один новый источник получил и немного изменил. кивок в старый vb 'With' block:
public abstract class With
{
public delegate void Operationdelegate<T>(T o);
public static void Each<T>(
IEnumerable<T> objects,
Operationdelegate<T> f)
{
foreach (var i in objects) f(i);
}
}
и использование:
// in this case (get data - do action with the entity):
With.Each(
_repository.Find(x => x.EmployeeID == 1),
t => Console.WriteLine(t.OrderDate));
просто осознал силу этого сегодня после того, как он в моем классе хранилища ничего не делал за годы ":)
было некоторое время, но вот небольшой метод расширения, который я собрал после повторения этого шаблона по крайней мере 3 раза в моем коде за последний день. В основном это берет исходный набор, группы в общем поле и возвращает значение MAX в этой группе, поэтому мы получаем подмножество max'd значение за ключ в исходной коллекции. Очевидно, что функция, выполняемая в совокупности, может быть любым действительным Func < > , который вам нравится (но это соответствует моей usecase):
public static class EnumerableUtils
{
public static IEnumerable<T> GroupAndAggregate<T, T2>(
this IEnumerable<T> source,
Func<T, T2> expressionGrp,
Func<T, T, T> expressionAggregate)
{
IEnumerable<T> ret = source.GroupBy(expressionGrp)
.Select(g => g.Aggregate(expressionAggregate));
return ret;
}
}
использование:
// use a previously created enumerable object
var result = grpResult.GroupAndAggregate(
g => g.FileLanguageCode,
(a, b) => (a.AddedDate > b.AddedDate) ? a : b);