How to sort List by custom Order - c#

Have some List of Application object
Application has Property Status and it holds values {"Red",Yellow,Blue ,Green and Orange")
My Requirement is to sort List in custom sort order
"Red" Should come first
"Blue" Second
"Yellow" Third
"Green" last
How to implement Sorting in this scenario .
Please help .
Thanks in advance

Well, you could create a list of sorted values and then sort by index in it:
var sortedValues = new List<string> {"Red", "Blue", "Yellow", "Green", "Orange"};
var result = myList.OrderBy(a => sortedValues.IndexOf(a.Status));

Define a new class with Id and Name of color property.
Create an array of the class and order the array by Id.
class CutomSort
{
class Color
{
public int Id;
public string Name;
}
static void Main(string[] args)
{
Color[] input = {
new Color{Id=4, Name="Green"},
new Color{Id=3, Name="Yellow"},
new Color{ Id=1, Name="Red"},
new Color{ Id = 2, Name = "Blue" }
};
IEnumerable<Color> result = input.OrderBy(x => x.Id);
foreach (Color color in result)
{
Console.WriteLine($"{color.Id}-{color.Name}");
}
Console.ReadKey();
}
}

Related

GroupBy dynamic list on multiple properties by using reflection

I have a class that defines some settings, one of this settings are the properties to group the list that you want to group by:
object of class MySetting
MySetting setting = new()
{
Groupby = $"{nameof(MyCss.Color)}, {nameof(MyCss.Width)}",
//.....
}
Now I have a dynamic list and I want to send this list as parameter with object setting to a method like ApplySetting, this method has to check if Groupby not a null and group my list:
public ApplySetting(List<TItem> myList, MySetting setting)
{
if(setting.Groupby != null)
{
var arr = setting.Groupby.Split(',', StringSplitOptions.RemoveEmptyEntries).ToList();
//do some this like, this wrong !
var groubs = myList.GroupBy(x => arr.ForEach(y => GetPropertyValue(y, x, x.GetType())))
}
}
Note: GetPropertyValue is a method that get value from object by using reflection.
Thanks for any help.
This is not solution with reflection you asked for but hack, but maybe it can serve you.
It uses lib System.Linq.Dynamic.Core and converts list to Queriable.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Dynamic.Core;
public class MySetting {
public string Groupby {get; set;}
}
public class ToGroupType{
public string Color {get; set;}
public string Width {get; set;}
}
public class Program
{
public static void Main()
{
MySetting setting = new()
{
Groupby = $"Color, Width",
//.....
};
static void ApplySetting<TItem>(List<TItem> myList, MySetting setting)
{
if(setting.Groupby != null)
{
//do some this like, this wrong !
var groubs = myList.AsQueryable().GroupBy($"new ({setting.Groupby})", "it").Select($"new (it.Key as Key , Count() as Count)").ToDynamicList();
Console.WriteLine(string.Join(",", groubs));
//result: Key = { Color = Red, Width = 10 }, Count = 2 },{ Key = { Color = Blue, Width = 10 }, Count = 2 },{ Key = { Color = Blue, Width = 15 }, Count = 1 }
}
}
ApplySetting(new List<ToGroupType>(){
new ToGroupType{Color = "Red", Width="10"},
new ToGroupType{Color = "Red", Width="10"},
new ToGroupType{Color = "Blue", Width="10"},
new ToGroupType{Color = "Blue", Width="10"},
new ToGroupType{Color = "Blue", Width="15"},
}, setting);
}}

To check a list and populate the value accordingly

I have a string list with values. I need to assign a value to a list based on the particular index of the string. Below is my code for the same.
var fruits = new string[] { "Color", "Price", "Shape ", "Nutrients" };
var fruitDetails = db.Fruits.Where(f => f.FruitId == 5).Select(f => new FruitModel{Id = f.FruitId,Category=f.Category, Color = f.FruitColor, Price=f.FruitPrice, Shape = f.FruitShape, Nutrients = f.FruitNutrients}).FirstOrDefault();
Now I need to populate a list using the results obtained from the Linq query based on the list of fruits.
foreach (var item in fruits )
{
var fruitData = new fruitData ();
fruitData.Category= fruitDetails .Category;
fruitData.Description= ; //This has to be the value of Color if item is color,value of price if item is price and so on...
fruitList.Add(fruitData);
}
So based on what the loop value is corresponding value needs to be populated. I do not want to be using Reflection. Is there an alternate method?
What if you use a switch statement like
switch (item)
{
case "Color":
fruitData.Description = fruitDetails.Color;
break;
case "Price":
fruitData.Description = fruitDetails.Price;
break;
case "Nutrient":
fruitData.Description = fruitDetails.Nutrient;
break;
default:
break;
}
I would suggest adding a property to FruitModel that returns the description based on the instance's Category, and that can use a static Dictionary to map categories to accessor functions:
public class FruitModel {
public int Id;
public string Category;
public string Color;
public double Price;
public string Shape;
public string Nutrients;
static Dictionary<string, Func<FruitModel, string>> catmap = new Dictionary<string, Func<FruitModel, string>> {
{ "Color", fm => fm.Color },
{ "Price", fm => fm.Price.ToString() },
{ "Shape", fm => fm.Shape },
{ "Nutrients", fm => fm.Nutrients },
};
public string Description {
get => catmap[Category](this);
}
public static List<string> FruitDetailCategories {
get => catmap.Keys.ToList();
}
}
You can also create a static property to return the detail categories rather than put the list somewhere else.
(Obviously you could use the switch instead of the Dictionary if preferred in the property body, but it doesn't lend itself to providing the detail categories.)
Now you can build your list easily:
var fruitList = new List<FruitData>();
foreach (var fruit in fruitDetails) {
var fd = new FruitData();
fd.Category = fruit.Category;
fd.Description = fruit.Description;
fruitList.Add(fd);
}

Filter a list based on value in an order?

What is the easiest way to filter a value with a null reference checking.Order should be like "Active",
"Reset",
"Locked",
"Suspended ",
"Expired",
"Disabled ",
"Revoked"
namespace ConsoleApplication1
{
class Program
{
private static void Main(string[] args)
{
var tempList = new List<string>
{
"Active",
"Reset",
"Locked",
"Suspended ",
"Expired",
"Disabled ",
"Revoked"
};
var list = new List<MyEntity>
{
new MyEntity() {MyValue = "Reset"},
new MyEntity() {MyValue = "Locked"},
new MyEntity() {MyValue = "Active"},
new MyEntity() {MyValue = "Expired"}
};
var item =
list.FirstOrDefault(x => x.MyValue));
}
}
public class MyEntity
{
public string MyValue { get; set; }
}
}
What I need to do to get the filter the list based on value ...
It sounds like you want to do an OrderBy and if you want the preference to be Sam, then Paul, then Jimmy, then Jeff, and then null if none of those are present then you can do the following.
var listOfNames = new List<string> { "Sam", "Paul", "Jimmy", "Jeff" };
var item = list.Where(x => listOfNames.Contains(x.MyValue))
.OrderyBy(x => listOfName.IndexOf(x.MyValue))
.FirstOrDefault();
This will first filter out anything that doesn't match the values you are interested it. Then orders them by their position in the list and finally picks the first one or null if the filter resulted in no matches.
Also I'm just assuming MyValue is a string here, but if you need to you can do whatever conversion is needed.

C# Questions Regarding Lists?

I have two classes: consumableItems.cs and items.cs
So basically, all I have to do is inherit the properties of items.cs to consumableItems.cs
Here's what I done so far:
class Item
{
public List<string> itemNames = new List<string>();
public List<int> itemEffects = new List<int>();
}
class consumableItems : Item
{
new public List<string> itemNames = new List<string>() { "Apple", "Orange", "Grapes" };
new public List<int> itemEffects = new List<int>() { 15, 30, 40 };
}
What I want to achieve is, whenever I type "Apple", the console window shows both "Apple" and "15"; same for when I type "Orange", the console window shows both "Orange" and "30". Any ideas? Sorry, just started C# programming and I'm getting lost. >< Oh, and last question, is the way I inherit correct? :/ Thanks. ^^
If you just starting with C# what about changing from List to Dictionnary ?
a Dictionary would give you what you want.
With two lists, you have to loop over the first one to find the index and then access the second list with the index. Be careful with Exception in that case.
Regarding inheritance, you should check for (public|private|Etc...) and maybe look for Interfaces and Abstract
You are re-inventing the wheel and making life hard. Just use a dictionary:
var items = new Dictionary<string, int>
{
{ "Apple", 15 },
{ "Orange", 30 },
{ "Grapes", 40 }
};
Console.WriteLine("Apple = {0}", items["Apple"]);
I propose you to define a class
class Item {
public string Name { get; set;}
public int Effect { get; set;}
}
And then use a single List<Item> instead of trying to map between the two lists. You could override the ToString() method of the class for your Console output.
Use Dictionary like in example below:
class Program2
{
class ConsumableItems
{
new public List<string> itemNames = new List<string>() { "Apple", "Orange", "Grapes" };
new public List<int> itemEffects = new List<int>() { 15, 30, 40 };
public Dictionary<string, int> values = new Dictionary<string, int>()
{
{"Apple", 15},
{"Orange", 30},
{"Grapes", 40}
};
}
static void Main()
{
ConsumableItems items = new ConsumableItems();
string key = Console.ReadLine();
Console.WriteLine("\n\n\n");
Console.WriteLine(key + " " + items.values[key]);
Console.ReadKey();
}
}
You can use Dictionary instead of List ,
public Dictionary<string, int> FruitValues = new Dictionary<string, int>()
{
{"Apple", 15},
{"Orange", 30},
{"Grapes", 40}
};
Console.WriteLine("Apple Value is {0}", FruitValues["Apple"]);
Same business problem can easily be solved by using any collection of Key-Value pair.. I mean using dictionary like:
public Dictionary<string, int> FruitsEffect= new Dictionary<string, int>()
FruitsEffect.Add("FruitsName",25);
The Dictionary has pairs of keys and values.Dictionary is used with different elements. We specify its key type and its value type (string, int).
Populate the dictionary and get the value by key.

Quick way to create a list of values in C#?

I'm looking for a quick way to create a list of values in C#. In Java I frequently use the snippet below:
List<String> l = Arrays.asList("test1","test2","test3");
Is there any equivalent in C# apart from the obvious one below?
IList<string> l = new List<string>(new string[] {"test1","test2","test3"});
Check out C# 3.0's Collection Initializers.
var list = new List<string> { "test1", "test2", "test3" };
If you're looking to reduce clutter, consider
var lst = new List<string> { "foo", "bar" };
This uses two features of C# 3.0: type inference (the var keyword) and the collection initializer for lists.
Alternatively, if you can make do with an array, this is even shorter (by a small amount):
var arr = new [] { "foo", "bar" };
In C# 3, you can do:
IList<string> l = new List<string> { "test1", "test2", "test3" };
This uses the new collection initializer syntax in C# 3.
In C# 2, I would just use your second option.
IList<string> list = new List<string> {"test1", "test2", "test3"}
You can do that with
var list = new List<string>{ "foo", "bar" };
Here are some other common instantiations of other common Data Structures:
Dictionary
var dictionary = new Dictionary<string, string>
{
{ "texas", "TX" },
{ "utah", "UT" },
{ "florida", "FL" }
};
Array list
var array = new string[] { "foo", "bar" };
Queue
var queque = new Queue<int>(new[] { 1, 2, 3 });
Stack
var queque = new Stack<int>(new[] { 1, 2, 3 });
As you can see for the majority of cases it is merely adding the values in curly braces, or instantiating a new array followed by curly braces and values.
You can drop the new string[] part:
List<string> values = new List<string> { "one", "two", "three" };
You can simplify that line of code slightly in C# by using a collection initialiser.
var lst = new List<string> {"test1","test2","test3"};
You can just:
var list = new List<string> { "red", "green", "blue" };
or
List<string> list = new List<string> { "red", "green", "blue" };
Checkout: Object and Collection Initializers (C# Programming Guide)
You can create helper generic, static method to create list:
internal static class List
{
public static List<T> Of<T>(params T[] args)
{
return new List<T>(args);
}
}
And then usage is very compact:
List.Of("test1", "test2", "test3")
If you want to create a typed list with values, here's the syntax.
Assuming a class of Student like
public class Student {
public int StudentID { get; set; }
public string StudentName { get; set; }
}
You can make a list like this:
IList<Student> studentList = new List<Student>() {
new Student(){ StudentID=1, StudentName="Bill"},
new Student(){ StudentID=2, StudentName="Steve"},
new Student(){ StudentID=3, StudentName="Ram"},
new Student(){ StudentID=1, StudentName="Moin"}
};
If we assume there is a class named Country , than we can do like this:
var countries = new List<Country>
{
new Country { Id=1, Name="Germany", Code="De" },
new Country { Id=2, Name="France", Code="Fr" }
};

Categories