Click here to Skip to main content
15,354,442 members
Please Sign up or sign in to vote.
1.00/5 (1 vote)
See more:
I have a list of Days
C#
List<string> days = new List<string>();


right now it only have Sun, Mon and Wednesday.

I also have an enum

C#
enum WeekDays
{
    Sunday,
    Monday,
    Tuesday,
    Wednesday,
    Thursday,
    Friday,
    Saturday,
}


i want to get the unused days
so the result should be Tuesday,Thursday,Friday and Sat.

What I have tried:

i tried to do multiple things but with no luck can u help. I'm new to c#
Posted
Updated 20-Apr-20 7:53am
v3
Comments
Nelek 20-Apr-20 6:46am
   
like a loop getting through all enum possibilities and asking the list to find each of them to see if they are used?

Try:
C#
private enum WeekDays
    {
    Sunday,
    Monday,
    Tuesday,
    Wednesday,
    Thursday,
    Friday,
    Saturday,
    }
public List<string> days = new List<string>();
private void DoSomat()
    {
    days.Add("Sunday");
    days.Add("Monday");
    days.Add("Wednesday");
    string[] allDays = Enum.GetNames(typeof(WeekDays));
    var missing = allDays.Except(days);
    ...
    }
   
v2
Comments
Member 14800672 20-Apr-20 8:43am
   
Thanks alot.
If i have variable (var)that has 2 objects
where the day equal concatenated value
[0] Sunday,Monday
[1] Wednesday,Thursday

I want to apply your solution on it
string[] allDays = Enum.GetNames(typeof(WeekDays));
var missing = allDays.Except(days);

so i want put in allDays.Except() all the days in the variable i mentioned above, how to do so?
OriginalGriff 20-Apr-20 8:58am
   
Don't.
You're mixing collections, so collate them first ionto a more "normal" form - you can use string.Split to break them up, and then combine them into a single array, List, or other collection.
By the sound of things, you have made a couple of bad decisions here - you should instead be thinking of using the enum as is, rather than relying on the the strings.
For example, if you specify the enum values as bits, you can combine them in a single enum value:
        private enum WeekDays
            {
            Sunday = 1,
            Monday = 2,
            Tuesday = 4,
            Wednesday = 8,
            Thursday = 16,
            Friday = 32,
            Saturday = 64,
            }

            WeekDays firstTwo = WeekDays.Sunday | WeekDays.Monday;
Which is a lot more efficient - and reliable - than strings.

Where is the comma separated data coming from?
Member 14800672 20-Apr-20 11:47am
   
Can you explain more, what i didn't get the bits and enum, can you show me how to do it?

the comma separated comes from this
var groupLast = groupFirst
.GroupBy(x => new { x.Day })
.Select(g => new
{
Day = g.Key.Day,
groupedBy = g
});
This group returns two objects:
Day = Sun,Mon
Day = wed,thur

i want to return Tuesday,Friday and Saturday
OriginalGriff 20-Apr-20 12:03pm
   
That doesn't do anything comma separated: it returns a collection of anonymous class objects with two properties: the Day (which hopefully is an enum value) and groupedby which a Group containing a collection of whatever objects were in groupFirst qwhen you started.

Commas aren't involved - except if you do something else with them ...
Have a look in the debugger - you'll see what I mean.
Member 14800672 20-Apr-20 13:31pm
   
GroupFirst does the comma seperation in days and it groups by another field
So it was first like
Sunday, Monday
Sunday, Monday
Wednesday, thursday
And the groupLast now groups by day to not get repeated values so
Sunday, Monday
Wed, Thursday
So day here is a field that comes from DB, that's why i made an enum to compare with it so will u be able to help now?
BillWoodruff 20-Apr-20 13:54pm
   
+5
Then you have a list of names of days, filled with only 3 names and need all the other days

First of all, You are trying to compare string values to WeekDays values, where the strings are supposed to be names of the WeekDays values.
C#
List<string> days = new List<string>();
days.Add(WeekDays.Sunday.ToString());
days.Add(WeekDays.Monday.ToString());
days.Add(WeekDays.Wednesday.ToString());

You cannot compare them without a conversion. The conversion can be either direction, depending on reuse chances.
- You can gather the names of all WeekDays values, using Enum.GetNames, in case storing in a temporary variable or in a static field to avoid repeating the operation.
- You can convert names of days list to WeekDays values, using Enum.Parse or Enum.tryParse, and store in a temporary variable; in this case, remember that Enum.Parse will throw on unrecognized/bad names.
In both cases you can use System.Linq.Enumerable.Except extension method.

Get all missing names as array, then convert them to values:
C#
var missingNames = Enum.GetNames(typeof(WeekDays)).Except(days).ToArray();
var missingValues = Array.ConvertAll(missingNames, value => (WeekDays)Enum.Parse(typeof(WeekDays), value, true));


Converts used names to values as enumerable sequence, then get all missing values as array:
C#
var daysValues = days.Select(value => (WeekDays)Enum.Parse(typeof(WeekDays), value, true));
var missingValues = ((WeekDays[])Enum.GetValues(typeof(WeekDays))).Except(daysValues).ToArray();


These are the most compact solutions, but I would break them into their composing steps, both for readability and maintenability purposes.
I suggest you to look into online help contents and local documentation for all the methods (Enum.Parse, Enum.TryParse, Enum.GetNames, Enum.GetValues, Array.ConvertAll, Enumerable.Select, Enumerable.Except, Enumerable.ToArray).
Keep in mind that these solutions produce array results, that are best suited in case you will perform several operations on them, and to debug them; if you will iterate only once, than at least the last ToArray invocation is not needed.

For Except method to work, you have to add using System.Linq; on top of the source file.
   
v2
Comments
BillWoodruff 20-Apr-20 11:56am
   
+5 very thorough !
[no name] 20-Apr-20 12:46pm
   
I think you forgot to click the stars :-) ... or the voting system has a bug.
BillWoodruff 20-Apr-20 14:33pm
   
Hi, thanks ! I thought I had voted.
If you are working with Enums a lot, you can use Extension Methods to hide complexity, and to develop and test separately from your main app code.

The two methods shown here extend either a string, or a Type; this is how they are called:

WeekDays monday = "Monday".ToEnum<WeekDays>();

WeekDays friday = typeof(WeekDays).ToEnum<WeekDays>("friday");

Once you have these "atomic methods," it is trivial to add other extensions that perform operations on collections using Linq.

imho, you do pay a price for either one: the first example extends string; I think extending basic types is generally a mistake. In the second example, you pay a price for the rather awkward structure of the calling format.
public static class EnumExtensions
{
    // string => Enum value
    public static TEnum ToEnum<TEnum>(this string str)
    where TEnum : struct, IConvertible
    {
        Type tenum = typeof(TEnum);

        if (! tenum.IsEnum)
            throw new ArgumentException("TEnum must be an Enum type");

        if (!Enum.IsDefined(tenum, str))
        {
            throw new ArgumentException($"{str} is not a valid string for conversion to {tenum.FullName}");
        }

        return (TEnum)Enum.Parse(tenum, str);
    }

    // Enum Type, string, optional bool => Enum value
    public static TEnum ToEnum<TEnum>(this Type tenum, string str, bool ignorecase = false)
        where TEnum : struct, IConvertible
    {
        if (! tenum.IsEnum)
            throw new ArgumentException("TEnum must be an Enum type");

        TEnum result;

        // note ignore case parameter
        if (Enum.TryParse<TEnum>(str, ignorecase, out result))
        {
            return result;
        }

        throw new ArgumentException($"{str} is not a valid string for conversion to {tenum.FullName}");
    }
}
   
v3

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900