Get values from enum - c#

I need find in enum DaysOfTheWeek values filtered by List<int> daysId and return filtered enum
My enum:
[Flags]
public enum DaysOfTheWeek
{
Sunday = 1,
Monday = 2,
Tuesday = 4,
Wednesday = 8,
Thursday = 16,
Friday = 32,
Saturday = 64,
AllDays = 127,
}
-
var allValues = Enum.GetValues(typeof(DaysOfTheWeek));
My integer list:
List<int> daysId = new List<int> {1,3};

var filtered = daysId.Select(d => (DaysOfTheWeek)d);

Not sure about your question. Something like this?
var filtered = daysId.Select(d=>(DaysOfTheWeek)(1<<(d-1))).ToList();

Maybe i'm over complicating, but check this out:
int[] daysId = new int[] { 1, 3,48,127 };
Dictionary<int, List<DaysOfTheWeek>> result = new Dictionary<int, List<DaysOfTheWeek>>();
foreach (int id in daysId)
{
result[id] = new List<DaysOfTheWeek>();
BitArray ba = new BitArray(new int[]{id});
for (int i=0;i<ba.Length;i++)
{
if (ba[i])
{
result[id].Add((DaysOfTheWeek)(1 << i));
Console.WriteLine((DaysOfTheWeek)(1 << i));
}
}
Console.WriteLine("id-" + id + " > " + (DaysOfTheWeek)id);
}
Console.ReadKey();
Check the output and see if it's what you want. You can use the direct conversion to days of week if you want so (DaysOfTheWeek)id or you can get each DaysOfTheWeek separately. I've done both up above.

Related

Alter a months list dynamically

I am stuck in a requirement.
I get two flags from the database, namely lastMonthNumber and lastMonthName, these can range from 1 to 12 and January to December.
Now I have a requirement such that if lastMonthName="March" and lastMonthNumner=12, then the parent list should be as below:
1, April
2, May
3, June
4, July
5, August
6, September
7, October
8, November
9, December
10, January
11, February
12, March
if lastMonthName="April" and lastMonthNumber=6, then the list should be:
7, November
8, December
9, January
10, February
11, March
12, April
This lastMonthNumber can range from 1 to 12 and lastMonthName too can range from Jan to Dec. The parent list needs to be dynamic.
If lastMonthNumber=6 and lastMonthName="April", then the list needs to have 6 elements with April as 12 and backtrack to have total 6 elements.
The parent list can be a dictionary, such as:
var monthsDictionary=new Dictionary<int, string>();
I am trying something as below, but not able to visualize further:
var monthsDictionary = new Dictionary<int, string>();
var numbers = new List<int> { 1,2,3,4,5,6,7,8,9,10,11,12};
var months = new List<string> {"January","February","March","April","May","June","July","August","September","October","November","December" };
foreach (var month in months.Select())
{
if (month == lastMonthName)
{
}
}
Please help. Pointers will be very helpful.
Have a constant with month names
private readonly string[] monthNames = { "Januar" ..., "December" };
and an accessor method that is able to cycle the index:
private string GetMonthName(int index)
{
if (index < 0) return monthNames[monthNames.Length - 1 - (index % monthNames.Length)];
return monthNames[index % monthNames.Length];
}
Then create the list:
int indexOfLastMonthName = Array.IndexOf(monthNames, lastMonthName);
var parentData = Enumerable
// Create as many items as last month number
.Range(0, lastMonthNumber)
// Create the list in reverse order, start on LastMonthName and 12,
// then go back with every item
.Select(x => new
{
Number = 12 - x,
Name = GetMonthName(indexOfLastMonthName - x)
}
// Turn it back
.Reverse();
Then fill it to an appropriate data structure. e.g. like this:
List<Tuple<int, string>> parentList = parentData
.Select(x => Tuple.Create(x.Number, x.Name)))
.ToList();
If you prefer a classic solution (using the GetMonthName method from above):
int indexOfLastMonthName = Array.IndexOf(monthNames, lastMonthName);
List<Tuple<int, string>> parentList = new List<Tuple<int, string>>();
for(int i = 0; i < lastMonthNumber; i++)
{
parentList.Add(
Tuple.Create(
12 - i,
GetMonthName(indexOfLastMonthName - i));
}
parentList.Reverse();
Try this linq query
var months = new List<string> {"January","February","March","April","May","June","July","August","September","October","November","December" };
var lastMonthNumber = ...;
var lastMonthName = ....;
var rows = months.Concat(months)
.Reverse()
.SkipWhile(m => m != lastMonthName)
.Take(lastMonthNumber)
.Reverse()
.Select((m, i) => new { id = i + 12 - lastMonthNumber + 1, m})
.ToArray();
It duplicate a months list, reverse it and skip items until lastMonthName found. After that this code limit result items count to lastMonthNumber and reverse list back
try the below fiddle.
https://dotnetfiddle.net/GYP2Go
private static Dictionary<int, string> GetRequiredResult(int lastMonthNumber, string lastMonthName)
{
var indx = months.IndexOf(lastMonthName);
// here this list will have months in required order that ends with lastMonthName
var revisedMonthList = new List<string>();
revisedMonthList.AddRange(months.Skip(indx + 1).Take(12));
revisedMonthList.AddRange(months.Take(indx + 1));
// get count = lastMonthNumber element from last using index, and then convert them to dictionary.
return revisedMonthList
.Select((mn, index) => new {index, mn})
.Where(c => c.index >= months.Count - lastMonthNumber)
.ToDictionary(c=>c.index + 1, c=>c.mn);
}
var monthsDictionary = new Dictionary<int, string>();
var numbers = new List<int> { 1,2,3,4,5,6,7,8,9,10,11,12};
var months = new List<string> {"January","February","March","April","May","June","July","August","September","October","November","December" };
int flag=0;
int items=12;
var numbersList = new List<int>();
var monthsList = new List<string>();
foreach (var month in months)
{
if(flag==0){
monthsList.Insert(items--,month);
if (month == lastMonthName)
{
flag=1;
}
}
else if(flag==1)
{
monthsList.add(month);
}
}
flag=0;
try following:
var months = Enumerable.Range(1, 12).Select(i => new
{
I = i,
M = System.Globalization.DateTimeFormatInfo.CurrentInfo.GetMonthName(i)
});
//string lastMonthName = "March"; int lastMonthNumber = 12;
//string lastMonthName = "April"; int lastMonthNumber = 6;
var selMonthInt = months.Where(x => x.M == lastMonthName).Select(y => y.I).FirstOrDefault();
int endCount = lastMonthNumber + selMonthInt;
if (endCount >= 12) { endCount = selMonthInt; }
var lst1 = months.Where(x => x.I > endCount).Select(z => z.M);
var lst2 = months.Where(x => x.I <= selMonthInt).Select(z => z.M);
var lst = lst1.Union(lst2).ToArray();
var selMonths = Enumerable.Range(0, lastMonthNumber).Select(i => new { I = (13 - lastMonthNumber + i), M = lst[i] });

Calculating the previous quarter from the current Month in C#

I'm sure there is a more consise way of achieving this result? However I created the following method to work out the previous quarter from the current month or DateTime passed in.
void Main()
{
var q = Helpers.PreviousQuarter();
q.Dump();
}
public class Helpers
{
public static int PreviousQuarter(DateTime? date = null)
{
var quarters = new Dictionary<int, int[]>();
quarters.Add(1, new[] { 1, 2, 3 });
quarters.Add(2, new[] { 4, 5, 6 });
quarters.Add(3, new[] { 7, 8, 9 });
quarters.Add(4, new[] { 10, 11, 12 });
foreach (var q in quarters)
{
if (q.Value.Any(m=> m == (date.HasValue ? date.Value.Month : DateTime.Now.AddMonths(-3).Month)))
return q.Key;
}
throw new ArgumentException("Could not calulate quarter.");
}
}
private int PreviousQuarter(DateTime date)
{
return (int)Math.Ceiling((double)date.AddMonths(-3).Month / (double)3);
}
This should do the trick
public static int PreviousQuarter(DateTime? date = null)
{
int month;
if (date.HasValue){
month = date.Value.Month;
} else {
month = DateTime.Now.AddMonths(-3).Month)
}
float quarter = month / 4;
return (int)Math.Ceiling(quarter +0.1);
}
Your current code is returning current quarter for a date you can modify your method like:
public static int CurrentQuarter(DateTime? date = null)
{
return (((date ?? DateTime.Now.AddMonths(-3)).Month - 1) / 3) + 1;
}
If you want to calculate previous quarter then you can use a single array instead of a dictionary like:
public static int PreviousQuarter(DateTime? date = null)
{
int[] previousQuarter = new[] {4, 4, 4, 1, 1, 1, 2, 2, 2, 3, 3, 3};
return previousQuarter[(date ?? DateTime.Now.AddMonths(-3)).Month];
}

How to find complex permutations based on and/or rules of lists of numbers, C#/Linq

The current problem is that the code works, but it gets exponentially slower as more combinations are passed in. (The calculation takes > 5 seconds after 15 combinations are passed in.) I need to be able to pass in up to 100 combinations and still get a result back that takes less than 2 seconds.
I'm betting that a Linq query could solve this?
What I want to achieve:
{1, 2, 3} + {1, 5, 26, 40} = 12 combinations:
[1,1]
[1,5]
[1,26]
[1,40]
[2,1]
[2,5]
[2,26]
[2,40]
[3,1]
[3,5]
[3,26]
[3,40]
However, this example above only includes 2 combination sets. I should be able to pass in any number of combination sets.
The closest thing that looks like it is similar to what I want as an end result, due to being fast and efficient, is a linq query that handles most or all of the logic within it. Example: Getting all possible combinations from a list of numbers
public IEnumerable<IEnumerable<T>> GetPowerSet<T>(List<T> list)
{
return from m in Enumerable.Range(0, 1 << list.Count)
select
from i in Enumerable.Range(0, list.Count)
where (m & (1 << i)) != 0
select list[i];
}
Example of working code:
[Test]
public void StackOverflowExample_Simple()
{
var list1 = new List<int>() { 1, 2, 3 };
var list2 = new List<int>() { 1, 5, 26, 40 };
var myListsOfNumberCombinations = new List<List<int>>() { list1, list2 };
var results = GetAllPossibleCombinations(myListsOfNumberCombinations);
Assert.AreEqual(12, results.Count());
StringBuilder sb = new StringBuilder();
foreach (var result in results)
{
foreach (var number in result.OrderBy(x => x))
{
sb.Append(number + ",");
}
sb.Append("|");
}
string finalResult = sb.ToString().Replace(",|", "|");
Assert.AreEqual(finalResult, "1,1|1,5|1,26|1,40|1,2|2,5|2,26|2,40|1,3|3,5|3,26|3,40|");
}
[Test]
public void StackOverflowExample_TakesALongTime()
{
var list1 = new List<int>() { 1, 2, 3 };
var list2 = new List<int>() { 4, 5 };
var list3 = new List<int>() { 1, 6 };
var list4 = new List<int>() { 2, 5 };
var list5 = new List<int>() { 1, 3, 55, 56 };
var list6 = new List<int>() { 3, 4, 7, 8, 9 };
var myListsOfNumberCombinations = new List<List<int>>() { list1, list2, list3, list4, list5, list1, list1, list1, list3, list4, list4, list5, list6, list6, list2 };
DateTime startTime = DateTime.Now;
var results = GetAllPossibleCombinations(myListsOfNumberCombinations);
Assert.AreEqual(4147200, results.Count());
var duration = DateTime.Now.Subtract(startTime).TotalSeconds;
//duration = about 4 or 5 seconds
Assert.Less(duration, 10); //easy place to put a breakpoint
}
public IEnumerable<IEnumerable<int>> GetAllPossibleCombinations(List<List<int>> combinationSets)
{
List<List<int>> returnList = new List<List<int>>();
_RecursiveGetMoreCombinations(
ref returnList,
new List<int>(),
combinationSets,
0);
return returnList;
}
private void _RecursiveGetMoreCombinations(
ref List<List<int>> returnList,
List<int> appendedList,
List<List<int>> combinationSets,
int index)
{
var combinationSet = combinationSets[index];
foreach (var number in combinationSet)
{
List<int> newList = appendedList.AsEnumerable().ToList();
newList.Add(number);
if (combinationSets.Count() == index + 1)
{
returnList.Add(newList);
}
else
{
_RecursiveGetMoreCombinations(
ref returnList,
newList,
combinationSets,
index + 1);
}
}
}
Can you not just do permutations of the first and third sets (the OR sets) and then place '45' (the AND set), or whatever the static numbers are, in between those numbers?
You don't need to include 4 and 5 (in this example) in the permutation logic if they are always going to be present.

How to populate a dataGridView with an array of user generated integers

With this:
dataGridView.DataSource = theData.Select((x, index) =>
new { CreatureRoll = x, CreatureLabel = index}).OrderByDescending(x => x.CreatureRoll).ToList();
It produces the data correctly, But it produces all the rows in the array with extra data that will not be useful, empty data.
img http://s21.postimg.org/t3f34aa43/list_Result.jpg?noCache=1379353500
Would like to remove unnecessary rows of data
You can have code like this also,
dataGridView1.Columns.Add("Index", "Index");
dataGridView1.Columns.Add("Value", "Dice Value");
int[] theData = new int[] { 5, 2, 1, 5, 4, 1, 3, 1};
for (int i = 0; i < theData.Length; i++)
{
dataGridView1.Rows.Add(new object[] { i+1, theData[i] });
}
Output
Take a look at this .NET / C# Binding IList<string> to a DataGridView
Setting the datasource to an array will not display anything. Basically the values need to have a named property and need to implement IList to be able to be used as a DataSource. Something like this should do your bidding.
var array = new int[] { 3, 4, 4, 5, 6, 7, 8 };
dataGridView1.AutoGenerateColumns = true;
dataGridView1.DataSource = array.Select(x => new { IntValue = x }).ToList();
You can use LINQ to generate the datasource from a array.
int[] theData = new int[] { 14, 17, 5, 11, 2 };
dataGridView1.DataSource = theData.Where(x => x>0).Select((x, index) =>
new { RecNo = index + 1, ColumnName = x }).OrderByDescending(x => x.ColumnName).ToList();
Try this:
int[] ints = new int[] { 1, 2, 3, 4, 5 };
gvMain.DataSource = ints;
gvMain.DataBind();
gvMain is a GridView, You can Add user generated array instead of ints.
how to assign the collection for below situation:
foreach (DataRow dr in dropDT.Rows)
{
values.Add(dr[0].ToString());
}
dataGridView1.Rows[e.RowIndex].Cells[4].Value = values;
dataGridView1.Rows[e.RowIndex].Cells[4].Value = values;

Conversion of System.Array to List

Last night I had dream that the following was impossible. But in the same dream, someone from SO told me otherwise. Hence I would like to know if it it possible to convert System.Array to List
Array ints = Array.CreateInstance(typeof(int), 5);
ints.SetValue(10, 0);
ints.SetValue(20, 1);
ints.SetValue(10, 2);
ints.SetValue(34, 3);
ints.SetValue(113, 4);
to
List<int> lst = ints.OfType<int>(); // not working
Save yourself some pain...
using System.Linq;
int[] ints = new [] { 10, 20, 10, 34, 113 };
List<int> lst = ints.OfType<int>().ToList(); // this isn't going to be fast.
Can also just...
List<int> lst = new List<int> { 10, 20, 10, 34, 113 };
or...
List<int> lst = new List<int>();
lst.Add(10);
lst.Add(20);
lst.Add(10);
lst.Add(34);
lst.Add(113);
or...
List<int> lst = new List<int>(new int[] { 10, 20, 10, 34, 113 });
or...
var lst = new List<int>();
lst.AddRange(new int[] { 10, 20, 10, 34, 113 });
There is also a constructor overload for List that will work... But I guess this would required a strong typed array.
//public List(IEnumerable<T> collection)
var intArray = new[] { 1, 2, 3, 4, 5 };
var list = new List<int>(intArray);
... for Array class
var intArray = Array.CreateInstance(typeof(int), 5);
for (int i = 0; i < 5; i++)
intArray.SetValue(i, i);
var list = new List<int>((int[])intArray);
Interestingly no one answers the question, OP isn't using a strongly typed int[] but an Array.
You have to cast the Array to what it actually is, an int[], then you can use ToList:
List<int> intList = ((int[])ints).ToList();
Note that Enumerable.ToList calls the list constructor that first checks if the argument can be casted to ICollection<T>(which an array implements), then it will use the more efficient ICollection<T>.CopyTo method instead of enumerating the sequence.
The simplest method is:
int[] ints = new [] { 10, 20, 10, 34, 113 };
List<int> lst = ints.ToList();
or
List<int> lst = new List<int>();
lst.AddRange(ints);
In the case you want to return an array of enums as a list you can do the following.
using System.Linq;
public List<DayOfWeek> DaysOfWeek
{
get
{
return Enum.GetValues(typeof(DayOfWeek))
.OfType<DayOfWeek>()
.ToList();
}
}
in vb.net just do this
mylist.addrange(intsArray)
or
Dim mylist As New List(Of Integer)(intsArray)
You can do like this basically:
int[] ints = new[] { 10, 20, 10, 34, 113 };
this is your array, and than you can call your new list like this:
var newList = new List<int>(ints);
You can do this for complex object too.
You can just give it try to your code:
Array ints = Array.CreateInstance(typeof(int), 5);
ints.SetValue(10, 0);
ints.SetValue(20, 1);
ints.SetValue(10, 2);
ints.SetValue(34, 3);
ints.SetValue(113, 4);
int[] anyVariable=(int[])ints;
Then you can just use the anyVariable as your code.
I know two methods:
List<int> myList1 = new List<int>(myArray);
Or,
List<int> myList2 = myArray.ToList();
I'm assuming you know about data types and will change the types as you please.
Just use the existing method.. .ToList();
List<int> listArray = array.ToList();
KISS(KEEP IT SIMPLE SIR)
I hope this is helpful.
enum TESTENUM
{
T1 = 0,
T2 = 1,
T3 = 2,
T4 = 3
}
get string value
string enumValueString = "T1";
List<string> stringValueList = typeof(TESTENUM).GetEnumValues().Cast<object>().Select(m =>
Convert.ToString(m)
).ToList();
if(!stringValueList.Exists(m => m == enumValueString))
{
throw new Exception("cannot find type");
}
TESTENUM testEnumValueConvertString;
Enum.TryParse<TESTENUM>(enumValueString, out testEnumValueConvertString);
get integer value
int enumValueInt = 1;
List<int> enumValueIntList = typeof(TESTENUM).GetEnumValues().Cast<object>().Select(m =>
Convert.ToInt32(m)
).ToList();
if(!enumValueIntList.Exists(m => m == enumValueInt))
{
throw new Exception("cannot find type");
}
TESTENUM testEnumValueConvertInt;
Enum.TryParse<TESTENUM>(enumValueString, out testEnumValueConvertInt);

Categories

Resources