[성현모] CPXV2 Init
This commit is contained in:
@ -0,0 +1,374 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace SystemX.Net.Platform.Common.ExtensionMethods
|
||||
{
|
||||
/// <summary>
|
||||
/// Linq extension methods
|
||||
/// </summary>
|
||||
public static partial class EmLinq
|
||||
{
|
||||
// http://stackoverflow.com/questions/1883920/call-a-function-for-each-value-in-a-generic-c-sharp-collection
|
||||
/// <summary>
|
||||
/// Generic IEnumerable ForEach extension : typename T is optional. deducible from source
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="source"></param>
|
||||
/// <param name="action"></param>
|
||||
|
||||
public static void ForEach<T>(this IEnumerable<T> source, Action<T> action)
|
||||
{
|
||||
foreach (T item in source)
|
||||
action(item);
|
||||
}
|
||||
|
||||
public static void Iter<T>(this IEnumerable<T> source, Action<T> action) => ForEach(source, action);
|
||||
public static void Iter<T>(this IEnumerable<T> source, Action<T, int> action)
|
||||
{
|
||||
int i = 0;
|
||||
foreach (T item in source)
|
||||
action(item, i++);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Lazy Foreach : Not evaluated until on demand
|
||||
/// </summary>
|
||||
public static IEnumerable<T> ForEachTee<T>(this IEnumerable<T> source, Action<T> action)
|
||||
{
|
||||
foreach (T item in source)
|
||||
{
|
||||
action(item);
|
||||
yield return item;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Non-Generic IEnumerable ForEach extension : typename T should be provided.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="source"></param>
|
||||
/// <param name="action"></param>
|
||||
public static void ForEach<T>(this IEnumerable source, Action<T> action)
|
||||
{
|
||||
foreach (T item in source)
|
||||
action(item);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Non-Generic IEnumerable ForEach extension : typename T should be provided.
|
||||
/// Lazy Foreach : Not evaluated until on demand
|
||||
/// </summary>
|
||||
public static IEnumerable ForEachTee<T>(this IEnumerable source, Action<T> action)
|
||||
{
|
||||
foreach (T item in source)
|
||||
{
|
||||
action(item);
|
||||
yield return item;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Non-Generic IEnumerable Select extension : typename T should be provided.
|
||||
/// </summary>
|
||||
/// <typeparam name="TSource"></typeparam>
|
||||
/// <typeparam name="TResult"></typeparam>
|
||||
/// <param name="source"></param>
|
||||
/// <param name="selector"></param>
|
||||
/// <returns></returns>
|
||||
public static IEnumerable<TResult> SelectEx<TSource, TResult>(this IEnumerable source, Func<TSource, TResult> selector)
|
||||
{
|
||||
foreach (TSource item in source)
|
||||
yield return selector(item);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// TResult type 의 enumerable 중에서 TNotCheckType type 이 아닌 것들만 골라서 반환한다. (System.Linq.OfType 의 negation)
|
||||
/// <para/> System.Linq.SkipWhile() 구문과 같은 역할
|
||||
/// <para/> TNotCheck 는 TResult type 이어야 함.
|
||||
/// </summary>
|
||||
/// <typeparam name="TResult">enumerable 들의 base type. 동시에 반환될 enumerable 의 type</typeparam>
|
||||
/// <typeparam name="TNotCheckType">제외할 type</typeparam>
|
||||
/// <param name="source"></param>
|
||||
/// <returns></returns>
|
||||
public static IEnumerable<TResult> OfNotType<TResult, TNotCheckType>(this IEnumerable source) where TNotCheckType : TResult
|
||||
{
|
||||
if (source == null) throw new ArgumentNullException("source");
|
||||
return OfNotTypeIterator<TResult, TNotCheckType>(source);
|
||||
}
|
||||
|
||||
|
||||
private static IEnumerable<TResult> OfNotTypeIterator<TResult, TNotCheckType>(IEnumerable source)
|
||||
{
|
||||
foreach (object obj in source)
|
||||
{
|
||||
if (!(obj is TNotCheckType))
|
||||
yield return (TResult)obj;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Select Non null element from enumerable
|
||||
/// </summary>
|
||||
public static IEnumerable<TResult> OfNotNull<TResult>(this IEnumerable<TResult> source) where TResult : class
|
||||
{
|
||||
if (source == null) throw new ArgumentNullException("source");
|
||||
foreach (var s in source)
|
||||
{
|
||||
if ( s != null )
|
||||
yield return s;
|
||||
}
|
||||
}
|
||||
|
||||
// http://stackoverflow.com/questions/2471588/how-to-get-index-using-linq
|
||||
public static Nullable<int> FindIndex<T>(this IEnumerable<T> items, Predicate<T> predicate)
|
||||
{
|
||||
int index = 0;
|
||||
foreach (var item in items)
|
||||
{
|
||||
if (predicate(item))
|
||||
return index;
|
||||
index++;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static HashSet<T> ToHashSet<T>(this IEnumerable<T> items)
|
||||
{
|
||||
var hash = new HashSet<T>();
|
||||
items.ForEach(i => hash.Add(i));
|
||||
return hash;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 두개의 set 이 동일한지 비교. see SequenceEqual
|
||||
/// </summary>
|
||||
public static bool SetEqual<T>(this IEnumerable<T> first, IEnumerable<T> second)
|
||||
{
|
||||
HashSet<T> firstSet = first.ToHashSet();
|
||||
foreach (var e in second)
|
||||
{
|
||||
if (!firstSet.Contains(e))
|
||||
return false;
|
||||
}
|
||||
|
||||
HashSet<T> secondSet = second.ToHashSet();
|
||||
foreach (var e in first)
|
||||
{
|
||||
if (!secondSet.Contains(e))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public static bool RemoveTail(this IList list)
|
||||
{
|
||||
if (list.IsNullOrEmpty())
|
||||
return false;
|
||||
|
||||
list.RemoveAt(list.Count - 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
public static T[] ConcatArrays<T>(params T[][] list)
|
||||
{
|
||||
var result = new T[list.Sum(a => a.Length)];
|
||||
int offset = 0;
|
||||
for (int x = 0; x < list.Length; x++)
|
||||
{
|
||||
list[x].CopyTo(result, offset);
|
||||
offset += list[x].Length;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
private static Tuple<bool, T> ExtractFirst<T>(this IEnumerable<T> seq)
|
||||
{
|
||||
using (var enumerator = seq.GetEnumerator())
|
||||
{
|
||||
if (enumerator.MoveNext())
|
||||
return Tuple.Create(true, enumerator.Current); // => return new Tuple<bool, T>(..) 와 동일
|
||||
|
||||
return Tuple.Create(false, default(T));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// http://stackoverflow.com/questions/4354902/check-that-all-items-of-ienumerablet-has-the-same-value-using-linq
|
||||
/// </summary>
|
||||
public static bool AllEqual<T>(this IEnumerable<T> source, T target)
|
||||
{
|
||||
using (var enumerator = source.GetEnumerator())
|
||||
{
|
||||
if (!enumerator.MoveNext())
|
||||
{
|
||||
// empty case
|
||||
return true;
|
||||
}
|
||||
|
||||
var comparer = EqualityComparer<T>.Default;
|
||||
|
||||
do
|
||||
{
|
||||
if (!comparer.Equals(target, enumerator.Current))
|
||||
return false;
|
||||
} while (enumerator.MoveNext());
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public static bool AllEqual<T>(this IEnumerable<T> source)
|
||||
{
|
||||
var pr = source.ExtractFirst();
|
||||
if (pr.Item1)
|
||||
return AllEqual(source, pr.Item2);
|
||||
|
||||
// empty case
|
||||
return true;
|
||||
}
|
||||
|
||||
public static T Tee<T>(this T input, Action action)
|
||||
{
|
||||
action();
|
||||
return input;
|
||||
}
|
||||
public static T Tee<T>(this T input, Action<T> action)
|
||||
{
|
||||
action(input);
|
||||
return input;
|
||||
}
|
||||
|
||||
public static bool ForAll<T>(this IEnumerable<T> source, Func<T, bool> predicate)
|
||||
{
|
||||
foreach (var s in source)
|
||||
{
|
||||
if (!predicate(s))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool ForAll<T>(this IEnumerable<T> source, Func<T, int, bool> predicate)
|
||||
{
|
||||
int i = 0;
|
||||
foreach (var s in source)
|
||||
{
|
||||
if (!predicate(s, i++))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public static bool NoForAll<T>(this IEnumerable<T> source, Func<T, bool> predicate)
|
||||
{
|
||||
foreach (var s in source)
|
||||
{
|
||||
if (predicate(s))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// source 를 n 개씩 분할한 sequence 를 반환
|
||||
/// http://stackoverflow.com/questions/419019/split-list-into-sublists-with-linq
|
||||
/// </summary>
|
||||
public static IEnumerable<IEnumerable<T>> SplitByN<T>(this IEnumerable<T> source, int n)
|
||||
{
|
||||
return source
|
||||
.Select((x, i) => new { Index = i, Value = x })
|
||||
.GroupBy(x => x.Index / n)
|
||||
.Select(x => x.Select(v => v.Value))
|
||||
;
|
||||
}
|
||||
|
||||
public static IEnumerable<T> EveryNth<T>(this IEnumerable<T> source, int n)
|
||||
{
|
||||
return source.Where((v, i) => i % n == 0);
|
||||
}
|
||||
|
||||
|
||||
public static IEnumerable<TResult> Zip2<TS1, TS2, TResult>(
|
||||
this IEnumerable<TS1> s1,
|
||||
IEnumerable<TS2> s2,
|
||||
Func<TS1, TS2, TResult> resultSelector) => s1.Zip(s2, resultSelector);
|
||||
|
||||
public static IEnumerable<TResult> Zip3<TS1, TS2, TS3, TResult>(
|
||||
this IEnumerable<TS1> s1,
|
||||
IEnumerable<TS2> s2,
|
||||
IEnumerable<TS3> s3,
|
||||
Func<TS1, TS2, TS3, TResult> resultSelector)
|
||||
{
|
||||
using (var e1 = s1.GetEnumerator())
|
||||
using (var e2 = s2.GetEnumerator())
|
||||
using (var e3 = s3.GetEnumerator())
|
||||
{
|
||||
while (e1.MoveNext() && e2.MoveNext() && e3.MoveNext())
|
||||
yield return resultSelector(e1.Current, e2.Current, e3.Current);
|
||||
}
|
||||
}
|
||||
|
||||
public static IEnumerable<TResult> Zip4<TS1, TS2, TS3, TS4, TResult>(
|
||||
this IEnumerable<TS1> s1,
|
||||
IEnumerable<TS2> s2,
|
||||
IEnumerable<TS3> s3,
|
||||
IEnumerable<TS4> s4,
|
||||
Func<TS1, TS2, TS3, TS4, TResult> resultSelector)
|
||||
{
|
||||
using (var e1 = s1.GetEnumerator())
|
||||
using (var e2 = s2.GetEnumerator())
|
||||
using (var e3 = s3.GetEnumerator())
|
||||
using (var e4 = s4.GetEnumerator())
|
||||
{
|
||||
while (e1.MoveNext() && e2.MoveNext() && e3.MoveNext() && e4.MoveNext())
|
||||
yield return resultSelector(e1.Current, e2.Current, e3.Current, e4.Current);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static IEnumerable<int> MinMaxRange(int min, int hop, int max)
|
||||
{
|
||||
if (hop <= 0)
|
||||
throw new ArgumentException("hop counter should be positive.");
|
||||
|
||||
for (int i = min; i <= max; i += hop)
|
||||
yield return i;
|
||||
}
|
||||
|
||||
public static IEnumerable<int> MinMaxRange(int min, int max) => Enumerable.Range(min, max - min);
|
||||
|
||||
public static IEnumerable<string> HexRange(int start, int count)
|
||||
{
|
||||
foreach (var h in Enumerable.Range(start, count))
|
||||
{
|
||||
yield return $"{h:X}";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Enumerable 의 laziness 를 강제로 실행시켜 evaluation 시킴.
|
||||
/// </summary>
|
||||
public static IEnumerable<T> Realize<T>(this IEnumerable<T> seq)
|
||||
{
|
||||
//var count = seq.Count(); // count 만으로는, 즉석 evaluation 이 안되는 경우가 존재...???...
|
||||
var array = seq.ToArray();
|
||||
return array;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user