Feedback

C# - Einfaches LINQ-Funktionen

Veröffentlicht von am 6/30/2015
(0 Bewertungen)
Ich verwende häufig LINQ, deshalb finde ich es auch sehr schade, dass es unter Mono nicht einsetzbar ist. :(

Zu diesem Zwecke habe ich mir einige eigene LINQ-Artige Funktionen entwickelt.

Der Code sollte selbsterklärend sein.
// 
// Abgeleitete Funktionen bekommen einen einen Wert vom Typen T
// und müssen zurückgeben, ob der Wert das gewünschte Kriterium erfüllt (true) oder nicht (false);
//
public delegate bool QueryServiceConditionFunc<T>(T value,int index);
//
// Diese Funktion erhält ein Objekt des Typens T und kann mit diesem nun arbeiten.
//
public delegate void QueryServiceFunc<T>(T value,int index);
//
// Da c# für die MonoRuntime derzeit scheinbar keine LINQ-Ausdrücke enthält,
// ist hier eine Implementierung, die einige der Funktionen übernehmen kann.
//
public static class QueryService
{
	//
	// Verwandelt eine IEnumerable in ein Array.
	//
	public static T[] ToArray<T>(this IEnumerable e)
	{
		var n = e.Count();
		T[] arr = new T[n];
		e.ForEach<T>((v, i) => {
			arr[i] = v;
		});
		return arr;
	}
	//
	// Versucht aus einer Sammlung von Elementen alle zu finden, 
	// für die eine bestimmte Bedingung gilt und gibt diese als neue Liste zurück.
	//
	public static T[] Select<T>(this IEnumerable e, QueryServiceConditionFunc<T> f)
	{
		List<T> res = new List<T>();
		e.ForEach<T>((v, i) => {
			if (f(v, i)) // Wenn die bedingung stimmt, zur Liste hinzufügen
				res.Add(v);
		});
		return res.ToArray();
	}
	//
	// Fügt alle Elemente in eine große Liste zusammen und gibt diese zurück.
	//
	public static T[] Join<T>(this IEnumerable e, params IEnumerable[] values)
	{
		List<T> res = new List<T>();
		e.ForEach<T>((v, i) => {
			res.Add(v); });
		foreach (var item in values) {
			item.ForEach<T>((v, i) => {
				res.Add(v); });
		}
		return res.ToArray();
	}
	//
	// Zählt nach, für wie viele Elemente die Bedingung gilt.
	//
	public static int CountContains<T>(this IEnumerable e, QueryServiceConditionFunc<T> f)
	{
		return e.Select(f).Length;
	}
	//
	// Bestimmt, ob in der List der bestimmte Wert vorkomment
	//
	public static bool Contains<T>(this IEnumerable e, T value)
	{
		var ee = e.GetEnumerator();
		do {
			if (Object.Equals((T)ee.Current, value))
				return true;
		} while (ee.MoveNext());
		return false; //Keine Übereinstimmung gefunden!
	}
	//
	// Gibt eine Liste von Werten zurück, die in beiden Listen vorkommen.
	//
	public static T[] Union<T>(this IEnumerable e, IEnumerable values)
	{
		Dictionary<T, int> d = new Dictionary<T, int>();
		foreach (var item in e) {
			d.Add((T)item, 0);
		}
		foreach (var item in values) {
			if (d.ContainsKey((T)item)) 
				d[(T)item]++; // Auf +1 erhöhen
				else {
				d.Add((T)item, 0);
			}
		}
		List<T> res = new List<T>();
		foreach (var item in d) {
			if (item.Value >= 1)
				res.Add(item.Key);
		}
		return res.ToArray();
	}
	//
	// Durchläuft für jedes Eleemtn eine Funktion func.
	//
	public static void ForEach<T>(this IEnumerable e, QueryServiceFunc<T> func)
	{
		var _enumerator = e.GetEnumerator();
		_enumerator.Reset();
		int index = 0;
		do {
			func((T)_enumerator.Current, index);
			index++;
		} while (_enumerator.MoveNext());
	}
	//
	// Addiert alle Werte, die in der Sammlung vorkommen.
	// Achtung: Der Type T muss eine Zahl sein (int).
	// Wenn andere Typen notwendig sind (uint etc.) einfach umschreiben.
	//
	public static int Sum<T>(this IEnumerable e)
	{
		int sum = 0;
		e.ForEach<int>((v, i) => {
			sum += v; });
		return sum;
	}
	//
	// Bestimmt den durchschnittlichen Wert aus der Liste. 
	// Achtung: Der Type T muss eine Zahl sein (int).
	// Wenn andere Typen notwendig sind (uint etc.) einfach umschreiben.
	//
	public static int Average<T>(this IEnumerable e)
	{
		return e.Sum<T>() / e.Count();
	}
	//
	// Bestimt den größten Wert.
	// Achtung: Der Type T muss eine Zahl sein (int).
	// Wenn andere Typen notwendig sind (uint etc.) einfach umschreiben.
	//
	public static int Max<T>(this IEnumerable e)
	{
		int max = int.MinValue;
		e.ForEach<int>((v, i) => {
			if (v > max)
				max = v;
		});
		return max;
	}
	//
	// Bestimmt den kleinsten Wert.
	// Achtung: Der Type T muss eine Zahl sein (int).
	// Wenn andere Typen notwendig sind (uint etc.) einfach umschreiben.
	//
	public static int Min<T>(this IEnumerable e)
	{
		int min = int.MaxValue;
		e.ForEach<int>((v, i) => {
			if (v < min)
				min = v;
		});
		return min;
	}
	//
	// Gibt das erste Elment oder Null zurück.
	//
	public static T FirstOrDefault<T>(this IEnumerable e)
	{
		var ee = e.GetEnumerator();
		ee.Reset();
		if (ee.MoveNext())
			return (T)ee.Current;
		return default(T); //return null
	}
	//
	// Versucht das Elemenent aus der Position zu erhalten.
	// Soltle es dieses nicht geben, wird null zurückgeben.
	// Es drüfgen keinen negativen Indizien verwendet werden.
	//
	public static T GetAt<T>(this IEnumerable e, uint index)
	{
		T ret = default(T);
		var ee = e.GetEnumerator();
		ee.Reset();
		for (uint i = 0; i <= index; i++) {
			if (!ee.MoveNext()) // Die Liste ist schon zuende
				return ret;
			else { // Auf Index prüfen
				if (i == index) // Der Index passt
					return (T)ee.Current;
			}
		}
		return ret;
	}
	//
	// Zählt die Anzahl der Elemente in der Liste.
	// Soltlen andere Zahlentypen benötigt werden (uint, long...),
	// so muss die Funktion abgeändert werden.
	//
	public static int Count(this IEnumerable e)
	{
		var _enumerator = e.GetEnumerator();
		int c = 0;
		do {
			c++;
		} while(_enumerator.MoveNext());
		return c;
	}
}	
Abgelegt unter LINQ, Mono, Daten, Verarbeitung.

Kommentare zum Snippet

 

Logge dich ein, um hier zu kommentieren!