how to add specific enum values to list in c# - c#

I have following enum and I want only C, E , F, H in the list
public enum myEnum{
A,
B,
C,
D,
E,
F,
G,
H
}
I have tried following and it will give all the enums
var listOfEnums = System.Enum.GetValues(typeof(myEnum)).Cast<myEnum>().ToList();

you can use attributes to retrieve only values that you want.
var listOfEnums = Enum
.GetValues(typeof(myEnum))
.Cast<myEnum>()
.Where(e => e.AttributeOfTypeExists<UsableInListAttribute>())
.ToList();
public static class EnumHelper
{
public static bool AttributeOfTypeExists<T>(this Enum enumVal)
where T : Attribute
{
var type = enumVal.GetType();
var memInfo = type.GetMember(enumVal.ToString());
return memInfo[0].GetCustomAttributes(typeof(T), false).Length > 0;
}
}
[AttributeUsage(AttributeTargets.Field)]
public class UsableInListAttribute : Attribute { }
public enum myEnum {
A,
B,
[UsableInList]
C,
D,
[UsableInList]
E,
[UsableInList]
F,
G,
[UsableInList]
H
}

I'm not sure, but try the following method:
If you want to have the C, E , F, H fields
var result = System.Enum.GetValues(typeof(myEnum)).Cast<myEnum>()
.Select(x => new { C = myEnum.C, E = myEnum.E, F = myEnum.F , H = myEnum.H })
.ToList();
If you want to filter C, E , F, H fields:
var result = System.Enum.GetValues(typeof(myEnum)).Cast<myEnum>()
.Where(x => x == myEnum.C || x == myEnum.E || x == myEnum.F || x == myEnum.H)
.ToList();

Is there a pattern that you're trying to match? Why not just try:
var listOfEnums = { myEnum.C, myEnum.E, myEnum.F, myEnum.H };

Related

IO Monad - stop and return default(T) when condition not satisfied in Linq?

The sum() in the following code will already get the sum of the a, b, c and 10 even if a < b (it will print the "We screwed up!" to indicate the expression failed the condition though). I tried to change the Where<T>(...) extension method to
public static IO<T> Where<T>(this IO<T> t, Func<T, bool> foo)
{
return () => (foo(t()) ? t : Combine(() => default(T), () => { Console.WriteLine("We screwed up!"); }))();
}
But it will get a NullReferenceException exception on select a + b + c + x? Why? There is no null value created?
class Program
{
static void Main(string[] args)
{
var A = new Monad.IO<int>(() => { Console.WriteLine("A"); return 6; });
var B = new Monad.IO<int>(() => { Console.WriteLine("B"); return 7; });
var C = new Monad.IO<int>(() => { Console.WriteLine("C"); return 10; });
var sum =
from a in A
from b in B
from c in C
let x = 10
where a > b // Should fail the whole expression and return default(T) because a < b
select a + b + c + x;
Console.WriteLine(sum());
}
}
static class Monad
{
public delegate T IO<out T>();
public static IO<R> SelectMany<S, C, R>(this IO<S> A, Func<S, IO<C>> foo, Func<S, C, R> bar)
{
var a = A();
var B = foo(a);
var b = B();
var c = bar(a, b);
return () => c;
// return () => bar(a, foo(a)());
}
public static IO<T> Combine<T>(IO<T> a, Action b)
{
return new Func<IO<T>, IO<T>>(x => { b(); return x; })(a);
}
public static IO<T> Where<T>(this IO<T> t, Func<T, bool> foo)
{
return () => (foo(t()) ? t : Combine(t, () => { Console.WriteLine("We screwed up!"); }))();
}
public static IO<R> Select<S, R>(this IO<S> s, Func<S, R> foo)
{
return () => new Func<IO<S>, R>(x => foo(x()))(s);
}
}
The code is from https://blogs.msdn.microsoft.com/alazarev/2017/05/20/fun-with-pure-c-and-monads/
In the query, foot(t()) is false, so you are taking the second half of the ternary, so you are returning (after Combine runs) default(T) where T is an anonymous type, so you are returning null.
Note that from a in A from b in B is translated into a call to SelectMany that creates a new anonymous type new { a, b } which is then passed to another SelectMany to handle the from c in C which results in another anonymous type new { new { a, b }, c }. Then the let causes a call to Select which returns another anonymous type new { new { a, b }, c}, x } which is what is passed into Where and the default(T) where T is an anonymous type is null.

How to write IEqualityComparer for anonymous variables in lambda expression?

I want to know there is a way to implement IEqualityComparer for anonymous variables in a lambda expression or, in any case, I need to write class to transform anonymous variables to the sprecific class and create a class where I need to implement IEqualtyComparer ?
I write code which create Cartesian(Decart's) production:
I defined class Decart.
public class Decart
{
public int X;
public int Y;
}
I defined IEqualtityComparer for Decart class
public class Ext : IEqualityComparer<Decart>
{
public bool Equals(Decart x, Decart y)
{
if ((x.X == y.X && x.Y == y.Y) ||
x.X == y.Y && x.Y == y.X)
return true;
return false;
}
public int GetHashCode(Decart obj)
{
return obj.X + obj.Y;
}
}
I run this code:
static void Main(string[] args)
{
Ext ext = new Ext();
IEnumerable<int> input = Enumerable.Range(1, 3);
var secondResult = input
.SelectMany(x => input.Select(y => new Decart{ X = x, Y = y }))
.Distinct(new Ext());
Console.WriteLine(new string('-', 50));
foreach (var x in secondResult)
{
Console.WriteLine(string.Format("{0} {1}", x.X, x.Y));
}
//output:
//1 1
//1 2
//1 3
//2 2
//2 3
//3 3
}
I want to run next code without defining a class for anonymous variables, a class for implementing IEqualityComparer.
var thirdResult = input
.SelectMany(x => input
.SelectMany(y => input
.Select(z => new { x, y, z })))
.Distinct( ???? );
//in this case output need to be like this:
//1 1 1
//1 2 1
//1 3 1
//2 1 2
//2 2 2
//2 3 2
//3 1 3
//3 2 3
//3 3 3
How to do it ?
You can declare IEqualityComparer<T> implementation which would take delegates as implementation for GetHashCode and Equals methods of interface. Then you can pass-in anonymous methods as implementation.
public static IEqualityComparer<T> CreateEqualityComparer<T>(T ignore, Func<T, int> getHashCode, Func<T, T, bool> equals) => new DelegatedEqualityComparer<T>(getHashCode, equals);
public class DelegatedEqualityComparer<T> : EqualityComparer<T> {
private Func<T, int> getHashCode;
private Func<T, T, bool> equals;
public DelegatedEqualityComparer(Func<T, int> getHashCode, Func<T, T, bool> equals) {
if(getHashCode==null) throw new ArgumentNullException(nameof(getHashCode));
if(equals==null) throw new ArgumentNullException(nameof(equals));
this.getHashCode=getHashCode;
this.equals=equals;
}
public override int GetHashCode(T x) => getHashCode(x);
public override bool Equals(T x, T y) => equals(x, y);
}
And you use it like this:
var equalityComparer = CreateEqualityComparer(true ? null : new { x = 0, y = 0 }, a => a.x+a.y, (a, b) => (a.x==b.x&&a.y==b.y)||(a.x==b.y&&a.y==b.x));
var result = input
.SelectMany(x => input
.Select(y => new { x, y }))
.Distinct(equalityComparer);
Meaning of true ? null : new { x = 0, y = 0 }:
First argument to CreateEqualityComparer (T ignore) is needed to allow compiler to infer type T, as you can not spell name of anonymous type. true condition of ternary operator make compiler to always select left branch null, but as both branches of ternary operator must return the same type, then new { x = 0, y = 0 } make compiler to implicitly cast null to given anonymous type.
Also, relevant note from specification:
7.6.10.6 Anonymous object creation expressions
Within the same program, two anonymous object initializers that specify a sequence of properties of the same names and compile-time types in the same order will produce instances of the same anonymous type.
It's unclear what you're asking.
I assume you want to generilize the dimensions of this class like
public class Decart
{
public int[] dim;
}
then you can extend the comparer
public class Ext : IEqualityComparer<Decart>
{
public bool Equals(Decart x, Decart y)
{
for(int i=0; i< x.dim.Length;i++)
if (x.dim[i] != y.dim[i] )
return false;
return true;
}
public int GetHashCode(Decart obj)
{
return obj.dim.Sum();
}
}

Lambda How to reordering elements in list ascending order and place null value at the back?

Says I have ListA={null,3,2,null}.
ListA.OrderBy(x=>x.ID) //would return me null,null,2,3
If my objective is to get 2,3,null,null, currently I can only think of extracting out the null item, and manually pump into the back.
Is there a clean approach where it will return me 2,3,null,null?
You can use OrderByDescending + ThenBy(assuming that it's aList<int?>):
var orderedList = ListA
.OrderByDescending(x => x.HasValue)
.ThenBy(x => x);
x.HasValue returns true or false where true is higher than false. That's why i'm using OrderByDescending.
If you want to sort the original list i would use List.Sort with a custom Compaison<T> that treats null as highest value:
ListA.Sort((a1, a2) => (a1 ?? int.MaxValue).CompareTo(a2 ?? int.MaxValue));
This is more efficient since it doesn't need to create a new list.
As an alternative to Tim's answer you could write your own IComparer<T> which does the custom sorting algorithm for you.
var array = list.OrderBy(x => x, new NullableIntComparer())
.ToArray();
class NullableIntComparer : IComparer<int?>
{
public int Compare(int? x, int? y)
{
if (x.HasValue && y.HasValue)
{
return x.Value.CompareTo(y.Value);
}
if (x.HasValue)
{
return -1;
}
if (y.HasValue)
{
return 1;
}
return 0;
}
}
Tried the following:
class Program
{
class A
{
public A(){}
public int? ID { get; set; }
}
static void Main(string[] args)
{
var listA = new List<A>
{
new A(){ID = null},
new A(){ID = 2},
new A(){ID = null},
new A(){ID = 3},
};
var result = listA.OrderByDescending(x => x.ID != null).ThenBy(x => x.ID);
foreach (var a in result)
{
Console.WriteLine(a.ID);
}
}
}

Given two collections A & B: want to output the inner join, elements in A that were not in B, elements in B that were not in A

Given two collections A & B, I want to output:
1. their inner join (say on a field called Id)
2. those elements in A that could not be found in B
3. those elements in B that could not be found in A
What is the most efficient way to do this?
When I say those elements in A that could not be found in B, I mean those elements that could not be "inner-joined" with B
For the inner join, have a look at the .Join() extension method: http://msdn.microsoft.com/en-us/library/bb344797.aspx
For the second 2 outputs, have a look at the .Except() extension method. http://msdn.microsoft.com/en-us/library/bb300779.aspx
For examples of most of the LINQ queries, have a look at this page: http://msdn.microsoft.com/en-us/vcsharp/aa336746
I guess I'd write this:
public class DeltaSet<T>
{
public ISet<T> FirstItems { get; private set; }
public ISet<T> SecondItems { get; private set; }
public ISet<Tuple<T, T>> IntersectedItems { get; private set; }
// T is the type of the objects, U is the key used to determine equality
public static DeltaSet<T> GetDeltaSet<T, U>(IDictionary<U, T> first,
IDictionary<U, T> second)
{
var firstUniques = new HashSet<T>(
first.Where(x => !second.ContainsKey(x.Key)).Select(x => x.Value));
var secondUniques = new HashSet<T>(
second.Where(x => !first.ContainsKey(x.Key)).Select(x => x.Value));
var intersection = new HashSet<Tuple<T, T>>(
second.Where(x => first.ContainsKey(x.Key)).Select(x =>
Tuple.Create(first[x.Key], x.Value)));
return new DeltaSet<T> { FirstItems = firstUniques,
SecondItems = secondUniques,
IntersectedItems = intersection };
}
public static DeltaSet<IDClass> GetDeltas(IEnumerable<IDClass> first,
IEnumerable<IDClass> second)
{
return GetDeltaSet(first.ToDictionary(x => x.ID),
second.ToDictionary(x => x.ID));
}
}
Assuming you have class A for elements in collection A and class B in collection B
class AB {
public A PartA;
public B PartB;
// Constructor
};
public void ManyJoin (List<A> colA, List<B> colB)
{
List<AB> innerJoin = new List<AB>();
List<A> leftJoin = new List<A>();
List<B> rightJoin = new List<B>();
bool[] foundB = new bool[colB.Count];
foreach (A itemA in colA)
{
int i = colB.FindIndex(itemB => itemB.ID == itemA.ID);
if (i >= 0)
{
innerJoin.Add (new AB(itemA, colB[i]));
foundB[i] = true;
}
else
leftJoin.Add(itemA);
}
for (int j = 0; j < foundB.count; j++)
{
if (!foundB[j])
rightJoin.Add(colB[j]);
}
}
This is one possible way. Whether it is optimum or not, I'm not sure, it does the job.

Get First 6 character from string which is distinct

string[] arr = { "abcdefXXX872358", "abcdef200X8XXX58", "abcdef200X872359", "6T1XXXXXXXXXXXX11", "7AbcdeHA30XXX541", "7AbcdeHA30XXX691" };
how can I get distinct numbers from above where first 6 character must be distinct
result would be
abcdefXXX872358
6T1XXXXXXXXXXXX11
7AbcdeHA30XXX541
I try something like this
var dist = (from c in arr
select c).Select(a => a.Substring(0, 5)).Distinct();
which gives me first 5 character but I want whole string
Group on the first characters, and get the first string in each group:
IEnumerable<string> firstInGroup =
arr
.GroupBy(s => s.Substring(0, 6))
.Select(g => g.First());
I think the best method would be to implement an IEqualityComparer, as is hinted by the overload on List.Distinct()
public class firstXCharsComparer : IEqualityComparer<string>
{
private int numChars;
public firstXCharsComparer(int numChars)
{
this.numChars = numChars;
}
public bool Equals(string x, string y)
{
return x.Substring(0, numChars) == y.Substring(0, numChars);
}
public int GetHashCode(string obj)
{
return obj.Substring(0, numChars).GetHashCode();
}
}
static void Main(string[] args)
{
string[] arr = { "abcdefXXX872358", "abcdef200X8XXX58", "abcdef200X872359", "6T1XXXXXXXXXXXX11", "7AbcdeHA30XXX541", "7AbcdeHA30XXX691" };
var result = arr.ToList().Distinct(new firstXCharsComparer(6));
result.Count();
}

Categories