Вот метод расширения в VB.NET для класса изображений
Imports System.Runtime.CompilerServices
Namespace Extensions
''' <summary>
''' Extensions for the Image class.
''' </summary>
''' <remarks>Several usefull extensions for the image class.</remarks>
Public Module ImageExtensions
''' <summary>
''' Extends the image class so that it is easier to get a thumbnail from an image
''' </summary>
''' <param name="Input">Th image that is inputted, not really a parameter</param>
''' <param name="MaximumSize">The maximumsize the thumbnail must be if keepaspectratio is set to true then the highest number of width or height is used and the other is calculated accordingly. </param>
''' <param name="KeepAspectRatio">If set false width and height will be the same else the highest number of width or height is used and the other is calculated accordingly.</param>
''' <returns>A thumbnail as image.</returns>
''' <remarks>
''' <example>Can be used as such.
''' <code>
''' Dim _NewImage as Image
''' Dim _Graphics As Graphics
''' _Image = New Bitmap(100, 100)
''' _Graphics = Graphics.FromImage(_Image)
''' _Graphics.FillRectangle(Brushes.Blue, New Rectangle(0, 0, 100, 100))
''' _Graphics.DrawLine(Pens.Black, 10, 0, 10, 100)
''' Assert.IsNotNull(_Image)
''' _NewImage = _Image.ToThumbnail(10)
''' </code>
''' </example>
''' </remarks>
<Extension()> _
Public Function ToThumbnail(ByVal Input As Image, ByVal MaximumSize As Integer, Optional ByVal KeepAspectRatio As Boolean = True) As Image
Dim ReturnImage As Image
Dim _Callback As Image.GetThumbnailImageAbort = Nothing
Dim _OriginalHeight As Double
Dim _OriginalWidth As Double
Dim _NewHeight As Double
Dim _NewWidth As Double
Dim _NormalImage As Image
Dim _Graphics As Graphics
_NormalImage = New Bitmap(Input.Width, Input.Height)
_Graphics = Graphics.FromImage(_NormalImage)
_Graphics.DrawImage(Input, 0, 0, Input.Width, Input.Height)
_OriginalHeight = _NormalImage.Height
_OriginalWidth = _NormalImage.Width
If KeepAspectRatio = True Then
If _OriginalHeight > _OriginalWidth Then
If _OriginalHeight > MaximumSize Then
_NewHeight = MaximumSize
_NewWidth = _OriginalWidth / _OriginalHeight * MaximumSize
Else
_NewHeight = _OriginalHeight
_NewWidth = _OriginalWidth
End If
Else
If _OriginalWidth > MaximumSize Then
_NewWidth = MaximumSize
_NewHeight = _OriginalHeight / _OriginalWidth * MaximumSize
Else
_NewHeight = _OriginalHeight
_NewWidth = _OriginalWidth
End If
End If
Else
_NewHeight = MaximumSize
_NewWidth = MaximumSize
End If
ReturnImage = _
_NormalImage.GetThumbnailImage(Convert.ToInt32(_NewWidth), Convert.ToInt32(_NewHeight), _Callback, _
IntPtr.Zero)
_NormalImage.Dispose()
_NormalImage = Nothing
_Graphics.Dispose()
_Graphics = Nothing
_Callback = Nothing
Return ReturnImage
End Function
End Module
End Namespace
Извините, кодовый тег не любит код vb.net.
Там не будет ничего встроенного в эти строки, но если вам это нужно часто, вы можете сделать что-нибудь индивидуальное, но довольно общее:
static IEnumerable<TSource> WhereRepeated<TSource>(
this IEnumerable<TSource> source)
{
return WhereRepeated<TSource,TSource>(source, x => x);
}
static IEnumerable<TSource> WhereRepeated<TSource, TValue>(
this IEnumerable<TSource> source, Func<TSource, TValue> selector)
{
using (var iter = source.GetEnumerator())
{
if (iter.MoveNext())
{
var comparer = EqualityComparer<TValue>.Default;
TValue lastValue = selector(iter.Current);
while (iter.MoveNext())
{
TValue currentValue = selector(iter.Current);
if (comparer.Equals(lastValue, currentValue))
{
yield return iter.Current;
}
lastValue = currentValue;
}
}
}
}
Использование:
foreach (Value value in values.WhereRepeated(x => x.Name))
{
Console.WriteLine(value.Name);
}
Вы можете подумать о том, что делать с тройками и т. д. - в настоящее время будет выдано все, кроме первого (что соответствует вашему описанию), но это может быть не совсем правильно.
Вы можете реализовать расширение Zip , затем заархивировать свой список с помощью .Skip (1), а затем выбрать строки, которые соответствуют.
Это должно работать и быть довольно простым в обслуживании:
values
.Skip(1)
.Zip(items, (first,second) => first.Name==second.Name?first:null)
.Where(i => i != null);
Небольшой недостаток этого метода в том, что вы дважды просматриваете список.
Я думаю, это сработает (непроверено) - это даст вам и повторяющееся слово, и его индекс. Для множественных повторов вы можете просмотреть этот список и проверить последовательные индексы.
var query = values.Where( (v,i) => values.Count > i+1 && v == values[i+1] )
.Select( (v,i) => new { Value = v, Index = i } );
Вот еще один простой подход это должно работать, если идентификаторы всегда последовательны, как в вашем примере:
var data = from v2 in values
join v1 in values on v2.Id equals v1.Id + 1
where v1.Name == v2.Name
select v2;
Что-то вроде этого
var dupsNames =
from v in values
group v by v.Name into g
where g.Count > 1 // If a group has only one element, just ignore it
select g.Key;
должно работать. Затем вы можете использовать результаты во втором запросе:
dupsNames.Select( d => values.Where( v => v.Name == d ) )
Это должно вернуть группировку с ключом = имя, значения = {элементы с именем}
Заявление об ограничении ответственности: я не тестировал вышеупомянутое, поэтому, возможно, я ошибаюсь.
Я знаю, что это древний вопрос, но я просто работал над тем же, так что ....
static class utils
{
public static IEnumerable<T> FindConsecutive<T>(this IEnumerable<T> data, Func<T,T,bool> comparison)
{
return Enumerable.Range(0, data.Count() - 1)
.Select( i => new { a=data.ElementAt(i), b=data.ElementAt(i+1)})
.Where(n => comparison(n.a, n.b)).Select(n => n.a);
}
}
Должно сработать для чего угодно - просто предоставьте функцию для сравнения элементов