Optimizing Double foreach loop - c#

I have a double foreach loop and want to speed it up by making it one loop instead of two.
The idea is that it takes one element from the dictionary and compares it against all elements in the dictionary
foreach (KeyValuePair<Int64, string> kvp in originCounts)
{
foreach (KeyValuePair<Int64, string> testkvp in originCounts)
{
//Run Comparison on testkvp ad kvp
}
}
I want to turn this into one loop, any suggestions?

You can use Enumerable.All to check if all elements are the same:
var firstID = originCounts.First().Value.UserID;
bool allEquals = originCounts.Skip(1).All(o => o.Value.UserID == firstID);
It seems that this is what you actually want.
I've just picked out a field of your class in the duplicate question that sounds as a reasonable identifier.
public class MyObject
{
public string FirstName{ get; set; }
public string LastName{ get; set; }
public int UserID { get; set; }
public string Address { get; set; }
}
Edit: According to your comment you want to determine if any of the objects' fields is different to the same field of another object.
var first = originCounts.First().Value;
bool allEquals = originCounts.Skip(1).All(o =>
o.Value.FirstName == first.FirstName
&& o.Value.LastName == first.LastName
&& o.Value.UserID == first.UserID
&& o.Value.Address == first.Address);

you could try this with linq syntax and compare performance
e.g.
foreach(KeyValuePair<long, string> kvp1 in originCounts.SelectMany(kvp1 => originCounts.Select(testkvp => kvp1), (kvp1, kvp) => kvp1)) {
}
or
foreach(KeyValuePair<long, string> kvp1 in from kvp1 in originCounts
from kvp in originCounts.Select(testkvp => kvp1)
select kvp1) {
}

You can create a comparable string key value class that implements the IComparable interface.
public class ComparableString : IComparable
{
public Int64 Key { get; set; }
public string Value { get; set; }
public int CompareTo(object obj)
{
if (obj == null) return 1;
string otherString = obj as ComparableString;
if (otherString != null)
{
// PLACE YOUR COMPARE LOGIC HERE
return this.Value.CompareTo(otherString.Value);
}
else
{
throw new ArgumentException("Object is not a Comparable String");
}
}
}
After doing that you can create a linked list and run the .sort method
var originCounts= new List<ComparableString>();
// Logic to fill your list
originCounts.Sort();
The average complexity is O(n(log n)) for the .Sort method and the worst case is O(n^2) see http://msdn.microsoft.com/en-us/library/b0zbh7b6.aspx for more information.
Once you call the .Sort() method you'll know that any value before the index of your item is less than or equal to the value of your item, and any index greater than the index of you're at is greater than or equal to the value of your item.

Perhaps I'm oversimplifying this by misunderstanding the question, but if you are just trying to find duplicate Values in a string, you can use the Values property of the Dictionary, and do a Distinct on them.
Using your example of a Dictionary:
Dictionary<Int64, string> originalCounts = new Dictionary<Int64, string>();
for (Int64 i = 0; i < 10; i++)
{
originalCounts.Add(i, i.ToString());
}
originalCounts[5] = originalCounts[3];
foreach (var kvp in originalCounts)
{
Console.WriteLine("{0} {1}", kvp.Key, kvp.Value);
}
Console.WriteLine();
foreach (var value in originalCounts.Values.Distinct())
{
Console.WriteLine("{0}", value);
}

If I understand correctly, to get the distinct objects (Which does not implement IComparable or override Equals and GetHashcode):
var noDups = originCounts
//Any Prop. you want to compare
.GroupBy(o => new { o.FirstName, o.LastName, o.UserID, o.Address })
.Select(g => g.First())
.ToList();

Why do you want to compare a dictionary entry to the other entries in the same dictionary? Are you checking for duplicates? If so, you can use originCounts.Distinct().
Edit: You would need to specify an IEqualityComparer for the Distinct method, otherwise it would only compare keys (which are always distinct in a Dictionary), not values.

Related

How to use IComparable to sort a dictionary of Class Objects

So I am trying to implement a sort on a dictionary to sort alphabetically by name. My class inherits IComparable and contains a compareTo(Object alpha)
method in the class. My problem is trying to implement this onto my dictionary and sort in that way.
I am reading from all names from a file and placing into a dictionary
I basically just want to know how to use this method since I could just extract name from the dictionary and sort then plug back in and get the other data I need. If anyone can help that would be great.
Here is the CompareTo method:
public int CompareTo(Object alpha)
{
if (alpha == null) throw new ArgumentNullException();
Subreddit rightOp = alpha as Subreddit;
if (rightOp != null)
return name.CompareTo(rightOp.name);
else
throw new ArgumentException("[Subreddit]:CompareTo argument is
not a Subreddit");
}
You can not use Dictionary<TKey,TValue> with IComparer<T> you should use SortedDictionary<TKey,TValue> instead. See https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.sorteddictionary-2?view=netframework-4.8 for details and examples
The new SortedDictionary<TKey,TValue>() will use Comparer<T>.Default and if type TKey implements the System.IComparable<T> generic interface, the default comparer uses that implementation. or you pass a comparer to the constructor. Here is an example
using System;
using System.Collections.Generic;
namespace ConsoleTestApp
{
class Program
{
static void Main(string[] args)
{
var sortedDictionary = new SortedDictionary<Subreddit, Payload>(new KeyComparer());
sortedDictionary.Add(new Subreddit {Name = "B"}, new Payload());
sortedDictionary.Add(new Subreddit {Name = "A"}, new Payload());
sortedDictionary.Add(new Subreddit {Name = "C"}, new Payload());
foreach (var keyValuePair in sortedDictionary)
{
Console.WriteLine($"{keyValuePair.Key.Name}");
}
Console.WriteLine("Press any key to exit program.");
Console.ReadKey();
}
}
public class Subreddit
{
public string Name { get; set; }
}
public class Payload
{
public string Data1 { get; set; }
public int Data2 { get; set; }
}
public class KeyComparer : IComparer<Subreddit>
{
public int Compare(Subreddit x, Subreddit y)
{
if (x?.Name == null)
throw new ArgumentException("[Subreddit]:CompareTo argument is not a Subreddit", nameof(x));
if (y?.Name == null)
throw new ArgumentException("[Subreddit]:CompareTo argument is not a Subreddit", nameof(y));
return string.Compare(x.Name, y.Name, StringComparison.Ordinal);
}
}
}
/*
The Output will be:
A
B
C
*/
If the key is a string only you do not need the class Subreddit with only one string property. You could simplify it to this and use the default implementation to sort strings.
using System;
using System.Collections.Generic;
namespace ConsoleTestApp
{
class Program
{
static void Main(string[] args)
{
var sortedDictionary = new SortedDictionary<string, Payload>();
sortedDictionary.Add("B", new Payload());
sortedDictionary.Add("A", new Payload());
sortedDictionary.Add("C", new Payload());
foreach (var keyValuePair in sortedDictionary)
{
Console.WriteLine($"{keyValuePair.Key}");
}
Console.WriteLine("Press any key to exit program.");
Console.ReadKey();
}
}
public class Payload
{
public string Data1 { get; set; }
public int Data2 { get; set; }
}
}
/*
The Output will be:
A
B
C
*/
Unlike List and Array Dictionary doesn't support sorting where you could implement IComparable interface and add your sort logic into CompareTo method.
But you can create your custom Comparer to use in OrderBy to somehow get the Dictionary items ordered as per your own requirement and return to a list of KeyValuePair. This is how you do this.
implement IComparer interface with given type, KeyValuePair TKey,TValue in your case, implement the Compare method with your comparison logic:
public class MyDictionaryComparer : IComparer<KeyValuePair<Subreddit, int>>
{
public int Compare(KeyValuePair<Subreddit, int> lhs, KeyValuePair<Subreddit, int> rhs)
{
return lhs.Key.name.CompareTo(rhs.Key.name);
}
}
Use:
Dictionary<Subreddit, int> data = new Dictionary<Subreddit, int>();
//Add some data
var sortedData = data.OrderBy(item => item, new MyDictionaryComparer());
Okay so what I ended up doing was creating an ArrayList of just Dicitonary.value.names
Then I call ArrayList.sort() which uses the IComparable interface and
my CompareTo(Object Alpha) to sort by name descending.
Once I had the sorted names in the array I used 2 foreach loops to compare the name values in the sorted ArrayList and the original dictionary with the other values I needed. Since I was checking the sorted ArrayList against the dictionary it automatically grabbed the data with the names in sorted Order.
From here I took all values associated with that name and threw it into another dictionary that was completely sorted. Now its probably not running at O(n) time but it works... Here's the code:
public void sortDictionaryByName()
{
//GOAL: Get all the values from the dictionary into a list that can use the
.sort method
ArrayList sortedNames = new ArrayList();
foreach (KeyValuePair<uint, Subreddit> value in subredditsDictionary)
{
sortedNames.Add(value.Value.name.ToString());
}
sortedNames.Sort();
foreach (var value in sortedNames)
{
foreach (KeyValuePair<uint, Subreddit> key in subredditsDictionary)
{
if (value.ToString() == key.Value.name.ToString())
{
Subreddit tempData = new Subreddit
{
subID = key.Key,
name = key.Value.name,
members = key.Value.members,
active = key.Value.active
};
sortedDictionary.Add(tempData.subID, tempData);
}
}
}
}

Convert List to Dictionary (a map of key and the filtered list as value)

class Animal
{
public FoodTypes Food { get;set;}
public string Name { get; set; }
}
enum FoodTypes
{
Herbivorous,
Carnivorous
}
class Util
{
public static Dictionary<FoodTypes,List<Animal>> GetAnimalListBasedOnFoodType(List<Animal> animals)
{
Dictionary<FoodTypes, List<Animal>> map = new Dictionary<FoodTypes, List<Animal>>();
var foodTypes = animals.Select(o => o.Food).Distinct();
foreach(var foodType in foodTypes)
{
if (!map.ContainsKey(foodType))
map.Add(foodType, null);
map[foodType] = animals.Where(o => o.Food == foodType).ToList();
}
return map;
}
}
The above code is to get the idea of what I am trying to achieve. Now, the question is
Is it possible to achieve the functionality of GetAnimalListBasedOnFoodType in a single lambda expression?
Here you go :)
public static Dictionary<FoodTypes, List<Animal>> GetAnimalListBasedOnFoodType(List<Animal> animals)
{
return animals
.GroupBy(animal => animal.Food)
.ToDictionary(
group => group.Key,
group => group.ToList());
}
You want to use the GroupBy method passing in the property that you want to group the animals by. Then, you can use the ToDictionary method to create your dictionary based on the grouping.
For example:
public static Dictionary<FoodTypes, List<Animal>> GetAnimalListBasedOnFoodType(List<Animal> animals)
{
var animalFoodMap = animals.GroupBy(animal => animal.Food)
.ToDictionary(animalGroup => animalGroup.Key, x => animalGroup.ToList());
return animalFoodMap;
}

c# sort list through by using int [duplicate]

I have a class called Order which has properties such as OrderId, OrderDate, Quantity, and Total. I have a list of this Order class:
List<Order> objListOrder = new List<Order>();
GetOrderList(objListOrder); // fill list of orders
I want to sort the list based on one property of the Order object; for example, either by the order date or the order id.
How can I do this in C#?
The easiest way I can think of is to use Linq:
List<Order> SortedList = objListOrder.OrderBy(o=>o.OrderDate).ToList();
If you need to sort the list in-place then you can use the Sort method, passing a Comparison<T> delegate:
objListOrder.Sort((x, y) => x.OrderDate.CompareTo(y.OrderDate));
If you prefer to create a new, sorted sequence rather than sort in-place then you can use LINQ's OrderBy method, as mentioned in the other answers.
To do this without LINQ on .Net2.0:
List<Order> objListOrder = GetOrderList();
objListOrder.Sort(
delegate(Order p1, Order p2)
{
return p1.OrderDate.CompareTo(p2.OrderDate);
}
);
If you're on .Net3.0, then LukeH's answer is what you're after.
To sort on multiple properties, you can still do it within a delegate. For example:
orderList.Sort(
delegate(Order p1, Order p2)
{
int compareDate = p1.Date.CompareTo(p2.Date);
if (compareDate == 0)
{
return p2.OrderID.CompareTo(p1.OrderID);
}
return compareDate;
}
);
This would give you ascending dates with descending orderIds.
However, I wouldn't recommend sticking delegates as it will mean lots of places without code re-use. You should implement an IComparer and just pass that through to your Sort method. See here.
public class MyOrderingClass : IComparer<Order>
{
public int Compare(Order x, Order y)
{
int compareDate = x.Date.CompareTo(y.Date);
if (compareDate == 0)
{
return x.OrderID.CompareTo(y.OrderID);
}
return compareDate;
}
}
And then to use this IComparer class, just instantiate it and pass it to your Sort method:
IComparer<Order> comparer = new MyOrderingClass();
orderList.Sort(comparer);
Simplest way to order a list is to use OrderBy
List<Order> objListOrder =
source.OrderBy(order => order.OrderDate).ToList();
If you want to order by multiple columns like following SQL Query.
ORDER BY OrderDate, OrderId
To achieve this you can use ThenBy like following.
List<Order> objListOrder =
source.OrderBy(order => order.OrderDate).ThenBy(order => order.OrderId).ToList();
Doing it without Linq as you said:
public class Order : IComparable
{
public DateTime OrderDate { get; set; }
public int OrderId { get; set; }
public int CompareTo(object obj)
{
Order orderToCompare = obj as Order;
if (orderToCompare.OrderDate < OrderDate || orderToCompare.OrderId < OrderId)
{
return 1;
}
if (orderToCompare.OrderDate > OrderDate || orderToCompare.OrderId > OrderId)
{
return -1;
}
// The orders are equivalent.
return 0;
}
}
Then just call .sort() on your list of Orders
A Classical Object Oriented Solution
First I must genuflect to the awesomeness of LINQ.... Now that we've got that out of the way
A variation on JimmyHoffa answer. With generics the CompareTo parameter becomes type safe.
public class Order : IComparable<Order> {
public int CompareTo( Order that ) {
if ( that == null ) return 1;
if ( this.OrderDate > that.OrderDate) return 1;
if ( this.OrderDate < that.OrderDate) return -1;
return 0;
}
}
// in the client code
// assume myOrders is a populated List<Order>
myOrders.Sort();
This default sortability is re-usable of course. That is each client does not have to redundantly re-write the sorting logic. Swapping the "1" and "-1" (or the logic operators, your choice) reverses the sort order.
// Totally generic sorting for use with a gridview
public List<T> Sort_List<T>(string sortDirection, string sortExpression, List<T> data)
{
List<T> data_sorted = new List<T>();
if (sortDirection == "Ascending")
{
data_sorted = (from n in data
orderby GetDynamicSortProperty(n, sortExpression) ascending
select n).ToList();
}
else if (sortDirection == "Descending")
{
data_sorted = (from n in data
orderby GetDynamicSortProperty(n, sortExpression) descending
select n).ToList();
}
return data_sorted;
}
public object GetDynamicSortProperty(object item, string propName)
{
//Use reflection to get order type
return item.GetType().GetProperty(propName).GetValue(item, null);
}
Using LINQ
objListOrder = GetOrderList()
.OrderBy(o => o.OrderDate)
.ToList();
objListOrder = GetOrderList()
.OrderBy(o => o.OrderId)
.ToList();
Here is a generic LINQ extension method that does not create an extra copy of the list:
public static void Sort<T,U>(this List<T> list, Func<T, U> expression)
where U : IComparable<U>
{
list.Sort((x, y) => expression.Invoke(x).CompareTo(expression.Invoke(y)));
}
To use it:
myList.Sort(x=> x.myProperty);
I recently built this additional one which accepts an ICompare<U>, so that you can customize the comparison. This came in handy when I needed to do a Natural string sort:
public static void Sort<T, U>(this List<T> list, Func<T, U> expression, IComparer<U> comparer)
where U : IComparable<U>
{
list.Sort((x, y) => comparer.Compare(expression.Invoke(x), expression.Invoke(y)));
}
Please let me complete the answer by #LukeH with some sample code, as I have tested it I believe it may be useful for some:
public class Order
{
public string OrderId { get; set; }
public DateTime OrderDate { get; set; }
public int Quantity { get; set; }
public int Total { get; set; }
public Order(string orderId, DateTime orderDate, int quantity, int total)
{
OrderId = orderId;
OrderDate = orderDate;
Quantity = quantity;
Total = total;
}
}
public void SampleDataAndTest()
{
List<Order> objListOrder = new List<Order>();
objListOrder.Add(new Order("tu me paulo ", Convert.ToDateTime("01/06/2016"), 1, 44));
objListOrder.Add(new Order("ante laudabas", Convert.ToDateTime("02/05/2016"), 2, 55));
objListOrder.Add(new Order("ad ordinem ", Convert.ToDateTime("03/04/2016"), 5, 66));
objListOrder.Add(new Order("collocationem ", Convert.ToDateTime("04/03/2016"), 9, 77));
objListOrder.Add(new Order("que rerum ac ", Convert.ToDateTime("05/02/2016"), 10, 65));
objListOrder.Add(new Order("locorum ; cuius", Convert.ToDateTime("06/01/2016"), 1, 343));
Console.WriteLine("Sort the list by date ascending:");
objListOrder.Sort((x, y) => x.OrderDate.CompareTo(y.OrderDate));
foreach (Order o in objListOrder)
Console.WriteLine("OrderId = " + o.OrderId + " OrderDate = " + o.OrderDate.ToString() + " Quantity = " + o.Quantity + " Total = " + o.Total);
Console.WriteLine("Sort the list by date descending:");
objListOrder.Sort((x, y) => y.OrderDate.CompareTo(x.OrderDate));
foreach (Order o in objListOrder)
Console.WriteLine("OrderId = " + o.OrderId + " OrderDate = " + o.OrderDate.ToString() + " Quantity = " + o.Quantity + " Total = " + o.Total);
Console.WriteLine("Sort the list by OrderId ascending:");
objListOrder.Sort((x, y) => x.OrderId.CompareTo(y.OrderId));
foreach (Order o in objListOrder)
Console.WriteLine("OrderId = " + o.OrderId + " OrderDate = " + o.OrderDate.ToString() + " Quantity = " + o.Quantity + " Total = " + o.Total);
//etc ...
}
Anybody working with nullable types, Value is required to use CompareTo.
objListOrder.Sort((x, y) => x.YourNullableType.Value.CompareTo(y.YourNullableType.Value));
//Get data from database, then sort list by staff name:
List<StaffMember> staffList = staffHandler.GetStaffMembers();
var sortedList = from staffmember in staffList
orderby staffmember.Name ascending
select staffmember;
An improved of Roger's version.
The problem with GetDynamicSortProperty is that only get the property names but what happen if in the GridView we use NavigationProperties? it will send an exception, since it finds null.
Example:
"Employee.Company.Name; " will crash... since allows only "Name" as a parameter to get its value.
Here's an improved version that allows us to sort by Navigation Properties.
public object GetDynamicSortProperty(object item, string propName)
{
try
{
string[] prop = propName.Split('.');
//Use reflection to get order type
int i = 0;
while (i < prop.Count())
{
item = item.GetType().GetProperty(prop[i]).GetValue(item, null);
i++;
}
return item;
}
catch (Exception ex)
{
throw ex;
}
}
You can do something more generic about the properties selection yet be specific about the type you're selecting from, in your case 'Order':
write your function as a generic one:
public List<Order> GetOrderList<T>(IEnumerable<Order> orders, Func<Order, T> propertySelector)
{
return (from order in orders
orderby propertySelector(order)
select order).ToList();
}
and then use it like this:
var ordersOrderedByDate = GetOrderList(orders, x => x.OrderDate);
You can be even more generic and define an open type for what you want to order:
public List<T> OrderBy<T,P>(IEnumerable<T> collection, Func<T,P> propertySelector)
{
return (from item in collection
orderby propertySelector(item)
select item).ToList();
}
and use it the same way:
var ordersOrderedByDate = OrderBy(orders, x => x.OrderDate);
Which is a stupid unnecessary complex way of doing a LINQ style 'OrderBy',
But it may give you a clue of how it can be implemented in a generic way
var obj = db.Items.Where...
var orderBYItemId = obj.OrderByDescending(c => Convert.ToInt32(c.ID));
Suppose you have the following code, in this code, we have a Passenger class with a couple of properties that we want to sort based on.
public class Passenger
{
public string Name { get; }
public string LastName { get; }
public string PassportNo { get; }
public string Nationality { get; }
public Passenger(string name, string lastName, string passportNo, string nationality)
{
this.Name = name;
this.LastName = lastName;
this.PassportNo = passportNo;
this.Nationality = nationality;
}
public static int CompareByName(Passenger passenger1, Passenger passenger2)
{
return String.Compare(passenger1.Name, passenger2.Name);
}
public static int CompareByLastName(Passenger passenger1, Passenger passenger2)
{
return String.Compare(passenger1.LastName, passenger2.LastName);
}
public static int CompareNationality(Passenger passenger1, Passenger passenger2)
{
return String.Compare(passenger1.Nationality, passenger2.Nationality);
}
}
public class TestPassengerSort
{
Passenger p1 = new Passenger("Johon", "Floid", "A123456789", "USA");
Passenger p2 = new Passenger("Jo", "Sina", "A987463215", "UAE");
Passenger p3 = new Passenger("Ped", "Zoola", "A987855215", "Italy");
public void SortThem()
{
Passenger[] passengers = new Passenger[] { p1, p2, p3 };
List<Passenger> passengerList = new List<Passenger> { p1, p2, p3 };
Array.Sort(passengers, Passenger.CompareByName);
Array.Sort(passengers, Passenger.CompareByLastName);
Array.Sort(passengers, Passenger.CompareNationality);
passengerList.Sort(Passenger.CompareByName);
passengerList.Sort(Passenger.CompareByLastName);
passengerList.Sort(Passenger.CompareNationality);
}
}
So you can implement your sort structure by using Composition delegate.
I made this extension method for List<T>.
The extension method takes the property you wish to sort as a parsed string and then uses the OrderBy method of the List<T>. Then it sets each index of the original list to the same index of the ordered list.
public static class ListExtensions {
public static void SortBy<T>(this List<T> list, string property, bool reverse = false) {
List<T> ordered = list.OrderBy(obj => obj.GetType().GetProperty(property).GetValue(obj, null)).ToList();
for (int i = 0; i < list.Count; i++)
list[i] = reverse ? ordered[list.Count - 1 - i] : ordered[i];
}
}
If an object in the list has the property Name you sort your list testList as so:
//For normal sorting order
testList.SortBy("Name");
//For reverse sorting order
testList.SortBy("Name", true);
I would recommend that you change the name of SortBy, to something like Prefix_SortBy. To prevent potential collisions if you import another library.
I know this method works for alphabetical and numerical ordering. Its sorting capabilites may be limited yet it is very simple to operate.
If there are some major flaws or issues with this, do tell, I've been programming C# for about 3 months.
Best regards
Make use of LiNQ OrderBy
List<Order> objListOrder=new List<Order> ();
objListOrder=GetOrderList().OrderBy(o=>o.orderid).ToList();
Based on GenericTypeTea's Comparer :
we can obtain more flexibility by adding sorting flags :
public class MyOrderingClass : IComparer<Order> {
public int Compare(Order x, Order y) {
int compareDate = x.Date.CompareTo(y.Date);
if (compareDate == 0) {
int compareOrderId = x.OrderID.CompareTo(y.OrderID);
if (OrderIdDescending) {
compareOrderId = -compareOrderId;
}
return compareOrderId;
}
if (DateDescending) {
compareDate = -compareDate;
}
return compareDate;
}
public bool DateDescending { get; set; }
public bool OrderIdDescending { get; set; }
}
In this scenario, you must instantiate it as MyOrderingClass explicitly( rather then IComparer )
in order to set its sorting properties :
MyOrderingClass comparer = new MyOrderingClass();
comparer.DateDescending = ...;
comparer.OrderIdDescending = ...;
orderList.Sort(comparer);
None of the above answers were generic enough for me so I made this one:
var someUserInputStringValue = "propertyNameOfObject i.e. 'Quantity' or 'Date'";
var SortedData = DataToBeSorted
.OrderBy(m => m.GetType()
.GetProperties()
.First(n =>
n.Name == someUserInputStringValue)
.GetValue(m, null))
.ToList();
Careful on massive data sets though. It's easy code but could get you in trouble if the collection is huge and the object type of the collection has a large number of fields.
Run time is NxM where:
N = # of Elements in collection
M = # of Properties within Object
If you need to sort the Id that is string in Question entity
Use Sort function and delegate to sort the Id after parsing the Id
value
class Question
{
public List<QuestionInfo> Questions Info{ get; set; }
}
class QuestionInfo
{
public string Id{ get; set; }
public string Questions{ get; set; }
}
var questionnaire = new Question();
questionnaire.QuestionInfo.Sort((x, y) => int.Parse(x.Id, CultureInfo.CurrentCulture) - int.Parse(y.Id, CultureInfo.CurrentCulture));
From performance point of view the best is to use a sorted list so that data is sorted as it is added to result.
Other approaches need at least one extra iteration on data and most create a copy of data so not only performance but memory usage will be affected too. Might not be an issue with couple of hundreds of elements but will be with thousands, especially in services where many concurrent requests may do sorting at the same time.
Have a look at System.Collections.Generic namespace and choose a class with sorting instead of List.
And avoid generic implementations using reflection when possible, this can cause performance issues too.
hi just to come back at the question.
If you want to sort the List of this sequence "1" "10" "100" "200" "2" "20" "3" "30" "300" and get the sorted items in this form 1;2;3;10;20;30;100;200;300 you can use this:
public class OrderingAscending : IComparer<String>
{
public int Compare(String x, String y)
{
Int32.TryParse(x, out var xtmp);
Int32.TryParse(y, out var ytmp);
int comparedItem = xtmp.CompareTo(ytmp);
return comparedItem;
}
}
and you can use it in code behind in this form:
IComparer<String> comparerHandle = new OrderingAscending();
yourList.Sort(comparerHandle);

How get an prop of Object key in a Dictionary C#?

I have this homework, I have only 1 problem, and I don't know the solution. We have this class, and we musn't create another variables or methods...
I have a beers dictionary with < Beer object, int income >. But the method has got only the Beer object's name (prop), not the object.
And I don't have another idea, how can I get the Beer object's name from a Dictionary
I have only 2 idea, but these don't work.
The first is I tried use a ContainsKey() method. The second is an foreach iteration
using System;
using System.Collections.Generic;
namespace PubBeer
{
public class Beer
{
string name;
int price;
double alcohol;
public string Name{ get { return name; } }
public int Price{ get; set; }
public double Alcohol{ get { return alcohol;} }
public Sör(string name, int price, double alcohol)
{
this.name= name;
this.price= price;
this.alcohol= alcohol;
}
public override bool Equals(object obj)
{
if (obj is Beer)
{
Beer other = (Beer)obj;
return this.name== other.name;
}
return false;
}
}
public class Pub
{
int income;
IDictionary<Beer, int> beers= new Dictionary<Beer, int>();
public int Income{ get; set; }
public int Sold(string beerName, int mug)
{
// Here the problem
beers; // Here I want to like this: beers.Contains(beerName)
// beers.ContainsKey(Object.Name==beerName) or someone like this
// foreach (var item in beers)
// {
// item.Key.Name== beerName;
// }
}
...
Use LINQ to query over the collection of Keys.
//Throws an error if none or more than one object has the same name.
var beer = beers.Keys.Single(b => b.Name == beerName);
beers[beer] = ...;
// -or -
//Selects the first of many objects that have the same name.
//Exception if there aren't any matches.
var beer = beers.Keys.First(b => b.Name == beerName);
beers[beer] = ...;
// -or -
//Selects the first or default of many objects.
var beer = beers.Keys.FirstOrDefault(b => b.Name == beerName);
//You'll need to null check
if (beer != null)
{
beers[beer] = ...;
}
// etc...
Update: NON-LINQ Alternative
Beer myBeer;
foreach (var beer in beers.Keys)
{
if (beer.Name == beerName)
{
myBeer = beer;
break;
}
}
if (myBeer != null)
{
beers[myBeer] = ...;
}
You could use Any() on the Keys collection:
if (beers.Keys.Any(x => x.Name == beerName))
{
}
In the worst case this would have to look through all beers though - if you usually look up beers by name you should consider making the beer name the key and the beer object itself the value in the dictionary.
Once you have identified that such a beer exists you can use First() to select it:
Beer myBeer = beers.First(x => x.Key.Name == beerName).Key;
try to use Keys property
beers.Keys.Where(p => p.name == beername )
or
beers.Keys.FirstOrDefault(p => p.name == beername)

how to check if List<T> element contains an item with a Particular Property Value

public class PricePublicModel
{
public PricePublicModel() { }
public int PriceGroupID { get; set; }
public double Size { get; set; }
public double Size2 { get; set; }
public int[] PrintType { get; set; }
public double[] Price { get; set; }
}
List<PricePublicModel> pricePublicList = new List<PricePublicModel>();
How to check if element of pricePublicList contains certain value. To be more precise, I want to check if there exists pricePublicModel.Size == 200? Also, if this element exists, how to know which one it is?
EDIT If Dictionary is more suitable for this then I could use Dictionary, but I would need to know how :)
If you have a list and you want to know where within the list an element exists that matches a given criteria, you can use the FindIndex instance method. Such as
int index = list.FindIndex(f => f.Bar == 17);
Where f => f.Bar == 17 is a predicate with the matching criteria.
In your case you might write
int index = pricePublicList.FindIndex(item => item.Size == 200);
if (index >= 0)
{
// element exists, do what you need
}
bool contains = pricePublicList.Any(p => p.Size == 200);
You can using the exists
if (pricePublicList.Exists(x => x.Size == 200))
{
//code
}
This is pretty easy to do using LINQ:
var match = pricePublicList.FirstOrDefault(p => p.Size == 200);
if (match == null)
{
// Element doesn't exist
}
You don't actually need LINQ for this because List<T> provides a method that does exactly what you want: Find.
Searches for an element that matches the conditions defined by the specified predicate, and returns the first occurrence within the entire List<T>.
Example code:
PricePublicModel result = pricePublicList.Find(x => x.Size == 200);
var item = pricePublicList.FirstOrDefault(x => x.Size == 200);
if (item != null) {
// There exists one with size 200 and is stored in item now
}
else {
// There is no PricePublicModel with size 200
}
You can also just use List.Find():
if(pricePublicList.Find(item => item.Size == 200) != null)
{
// Item exists, do something
}
else
{
// Item does not exist, do something else
}

Categories

Resources