A shorter way to write the following function in C#? - c#

I have this function -
public int GetAvgResult()
{
var weeklyvalues=GetWeeklyValues();//gets list of weekly values.
if (weeklyvalues.Count == 0)
return 0;
return (weeklyvalues.Sum() / weeklyvalues.Count);
}
Is there a shorter way to write this using ?: or maybe something else ?

public double GetAvgResult()
{
// Assumes GetWeeklyValues() never returns null.
return GetWeeklyValues().DefaultIfEmpty().Average();
}
Do note that this returns a double , which I assume is what you really want (the average of a bunch of integers is logically not an integer). You can cast it to int if necessary, or if you want to stick with integer math all the way:
var seq = GetWeeklyValues().DefaultIfEmpty();
return seq.Sum() / seq.Count();

public int GetAvgResult()
{
var weeklyvalues = GetWeeklyValues();
return (weeklyvalues.Count != 0) ? (weeklyvalues.Sum() / weeklyvalues.Count) : 0;
}
or:
public int GetAvgResult()
{
return GetWeeklyValues().DefaultIfEmpty().Average();
}

public int GetAvgResult()
{
var weeklyvalues = GetWeeklyValues(); //gets list of weekly values.
return weeklyvalues.Count == 0 ? 0 : weeklyvalues.Sum() / weeklyvalues.Count;
}
That's as short as I'd attempt to make it. Is there a specific reason (other than code golf) you're trying for a low character count?

public int GetAvgResult()
{
var weeklyvalues = GetWeeklyValues();//gets list of weekly values.
return (weeklyvalues.Count == 0) ? 0 : (weeklyvalues.Sum() / weeklyvalues.Count );
}

public int GetAvgResult()
{
var weeklyvalues=GetWeeklyValues();//gets list of weekly values.
return weeklyvalues.Count == 0
? 0
: (weeklyvalues.Sum() / weeklyvalues.Count);
}

Related

Is there an easier way to parse an int to a generic Flags enum?

I've got a generic function to parse an object into a generic Enum.
However, I'm running into an issue when trying to safely parse an int into a [Flags] Enum.
Directly using Enum.ToObject() works to parse valid combinations, but will just return the original value if there isn't a flag combination.
Additionally, when there's no explicit enum member for a combination of flags, Enum.ToName() and Enum.IsDefined() don't return helpful values.
For Example:
[Flags]
public enum Color
{
None = 0,
Red = 1,
Green = 2,
Blue = 4,
}
// Returns 20
Enum.ToObject(typeof(Color), 20)
// Returns ""
Enum.ToName(typeof(Color), 3)
// Returns false
Enum.IsDefined(typeof(Color), 3)
I've written a function that I think technically works, but it seems like there has to be a better way to do this.
My Function:
public static T ParseEnumerator<T>(object parseVal, T defaultVal) where T : struct, IConvertible
{
Type ttype = typeof(T);
if (!ttype.IsEnum)
{
throw new ArgumentException("T must be an enumerated type");
}
bool isFlag = ttype.GetCustomAttribute(typeof(FlagsAttribute)) != null;
try
{
if (parseVal == null)
{
return defaultVal;
}
else if (parseVal is T)
{
return (T)parseVal;
}
else if (parseVal is string)
{
return (T)Enum.Parse(ttype, parseVal.ToString(), true);
}
//**************** The section at issue **********************************/
else if (isFlag && parseVal is int)
{
List<string> flagsList = new List<string>();
int maxVal = 0;
//Loop through each bit flag
foreach (var val in Enum.GetValues(ttype))
{
if (CountBits((int)val) == 1)
{
if ((int)val > maxVal)
maxVal = (int)val;
// If the current bit is set, add the flag to the result
if (((int)parseVal & (int)val) == (int)val)
{
string enumName = Enum.GetName(ttype, val);
if (!string.IsNullOrEmpty(enumName))
flagsList.Add(enumName);
}
}
}
// Is the value being parsed over the highest bitwise value?
if ((int)parseVal >= (maxVal << 1))
return defaultVal;
else
return (T)Enum.Parse(ttype, string.Join(",", flagsList));
}
//************************************************************************/
else
{
string val = Enum.GetName(ttype, parseVal);
if (!string.IsNullOrEmpty(val))
return (T)Enum.ToObject(ttype, parseVal);
else
return defaultVal;
}
}
catch
{
return defaultVal;
}
}
Is there something I'm missing? Or is there another way to parse these values safely?
Any help is appreciated, thanks!
-MM
Since your generic function has to know the Enum type to begin with, you can just scrap the function and use basic casting instead.
using System;
namespace SO_58455415_enum_parsing {
[Flags]
public enum CheeseCharacteristics {
Yellow = 1,
Mouldy = 2,
Soft = 4,
Holed = 8
}
public static class Program {
static void Main(string[] args) {
CheeseCharacteristics cc = (CheeseCharacteristics)12;
Console.WriteLine(cc);
}
}
}
If all you want to know is if you have a value that can be created using the enum flags.. that's pretty easy, as long as we can assume that each flag is "sequential" (e.g. there are no gaps between the flags). All numbers between 1 and the sum of all flag values can be made by some combination of flags. You can simply sum the flag values together and compare that to your question value.
public static bool IsValidFlags<T>(int checkValue) where T:Enum {
int maxFlagValue = ((int[])Enum.GetValues(typeof(T))).Sum();
return (0 < checkValue) && (checkValue <= maxFlagValue);
}
For future reference, you can constrain your generic parameter to an enum:
void fx<T> () where T:Enum { }

How to validate decimal places

Please let me know good way to validate decimal value, if decimal(4,2) it should accept 2 numeric and 2 decimal places.
var value = "44.29";
var dec = value.Split('.');
Then finding the length will can be used, I need a better culture specific way. I need a generic solution which can be applied to all decimal field.
Like:
validate(int before,int afterdecimal);
var valid = validate(2,2);
Need a generic cleaner solution for this
private static bool IsDecimal(string value, int before, int after)
{
if (value.Contains("."))
{
var parts = value.Split('.');
if (parts[0].Length == before && parts[1].Length == after)
return true;
}
else if(value.Length == before)
return false;
return true;
}
You can try like this:
[RegularExpression(#"^\d{1,2}(\.\d{0,2})$",ErrorMessage = "Value contains more than 2 decimal places")]
public decimal Value { get; set; }
If you whant just validate, try to use the mod:
44.29 % 1 = 0.29
From the above answers I was able to do it like this
string value = "2009.99";
if (IsDecimal(value, 4, 4))
{
Console.WriteLine("Valid");
}
private static bool IsDecimal(string value, int before, int after)
{
var r = new Regex(#"^\d{1," + before + #"}(\.\d{0," + after + #"})$");
return r.IsMatch(value);
}

Refactoring if-else if - else

I have the following code example
if(object.Time > 0 && <= 499)
{
rate = .75m
}
else if(object.Time >= 500 && <= 999)
{
rate = .85m
}
else if(object.Time >= 1000)
{
rate = 1.00m
}
else
{
rate = 0m;
}
My question is what design pattern can I use to make this better?
Edit: Just to clarify a little better, the code you see here is something that currently exists within a Strategy Pattern Implementation. We have 3 types of calculations 2 of which has 3 different "rates" that could be used based off of the time you see below. I thought about creating a strategy implementation for each rate, but then I would be moving the logic for determining the strategy to use and make that a mess as well.
Thanks!
If you're really looking for a design pattern, I'd go for the Chain of Responsibility pattern.
Basically your "link" tries to handle the input. If it is unable to handle it, it's passed down the chain until an other link can handle it. You can also define an interface for easy mocking in your unit tests, if you have some.
So you have this abstract class that every link will inherit :
public abstract class Link
{
private Link nextLink;
public void SetSuccessor(Link next)
{
nextLink = next;
}
public virtual decimal Execute(int time)
{
if (nextLink != null)
{
return nextLink.Execute(time);
}
return 0;
}
}
And then you create each links with your rules :
public class FirstLink : Link
{
public override decimal Execute(int time)
{
if (time > 0 && time <= 499)
{
return .75m;
}
return base.Execute(time);
}
}
public class SecondLink : Link
{
public override decimal Execute(int time)
{
if (time > 500 && time <= 999)
{
return .85m;
}
return base.Execute(time);
}
}
public class ThirdLink : Link
{
public override decimal Execute(int time)
{
if (time >= 1000)
{
return 1.00m;
}
return base.Execute(time);
}
}
Finally, to use it, just set every successor and call it :
Link chain = new FirstLink();
Link secondLink = new SecondLink();
Link thirdLink = new ThirdLink();
chain.SetSuccessor(secondLink);
secondLink.SetSuccessor(thirdLink);
and all you have to do, is call the chain with one clean call:
var result = chain.Execute(object.Time);
There is a not so famous pattern called 'Rules Pattern'
The idea is that everything is extracted into an object and let it handle its own job. You will have each class for each rule that you defined which is your condition statement, e.g. (object.Time > 0 && <= 499)
public class RuleNumberOne : IRules
{
public decimal Execute(Oobject date)
{
if(date.Time > 0 && date.Something <= 499)
return .75m;
return 0;
}
}
public class RuleNumberTwo : IRules
{
public decimal Execute(Oobject date)
{
if(date.Time >= 500 && date.Something <= 999)
return .85m;
return 0;
}
}
public interface IRules
{
decimal Execute(Oobject date);
}
Therefore, on your class that used to look like this
if(object.Time > 0 && <= 499)
{
rate = .75m
}
else if(object.Time >= 500 && <= 999)
{
rate = .85m
}
else if(object.Time >= 1000)
{
rate = 1.00m
}
else
{
rate = 0m;
}
Will now be,
private List<IRules>_rules = new List<IRules>();
public SomeConstructor()
{
_rules.Add(new RuleNumberOne());
_rules.Add(new RuleNumberTwo());
}
public void DoSomething()
{
Oobject date = new Oobject();
foreach(var rule in this._rules)
{
Decimal rate = rule.Execute(date);
}
}
The idea here is that once you get nested if conditions, it would be harder to read the condition statements and its hard for the developer to make any changes. Thus, it separates the logic of each individual rule and its effect into its own class which follows the rule Single Responsibility Pattern.
Some considerations are
1.) Read only
2.) Explicit order
3.) Dependencies
4.) Priority
5.) Persistence
Again, consider using the Rules Pattern when you have a growing amount of conditional complexity and your application's requirements warrants it.
You can customize it if you want don't want it to return decimal or something but the idea is here.
You only need to check one endpoint of the range. The other one is implied by your actually being at that point in the code, since the earlier conditions were false.
if (obj.Time <= 0) {
rate = 0.00m;
}
// At this point, obj.Time already must be >= 0, because the test
// to see if it was <= 0 returned false.
else if (obj.Time < 500) {
rate = 0.75m;
}
// And at this point, obj.Time already must be >= 500.
else if (obj.Time < 1000) {
rate = 0.85m;
}
else {
rate = 1.00m;
}
It would be better to make the more common end of the scale the one you check first, for readability and performance reasons. But it'll work either way.
Using a map:
var map = new[]
{
new { Rule = (Func<Oobject, bool>) ( x => x.Time > 0 && x.Something <= 499 ),
Value = .75m },
new { Rule = (Func<Oobject, bool>) ( x => x.Time >= 500 && x.Something <= 999 ),
Value = .85m },
new { Rule = (Func<Oobject, bool>) ( x => true ),
Value = 0m }
};
var date = new Oobject { Time = 1, Something = 1 };
var rate = map.First(x => x.Rule(date) ).Value;
Assert.That( rate, Is.EqualTo(.75m));
I like the idea of #lll's Rules Pattern answer but it has a flaw.
Consider the following test (NUnit):
[Test]
public void TestRulesUsingList()
var rules = new IRules[]{ new RuleNumberOne(), new RuleNumberTwo() };
var date = new Oobject { Time = 1, Something = 1 };
var rate = 0m;
foreach(var rule in rules)
rate = rule.Execute(date);
Assert.That( rate, Is.EqualTo(.75m));
}
The test fails. Although RuleNumberOne was called and returned a non-zero value, RuleNumberTwo was subsequently called and returned zero to overwrite the correct value.
In order to replicate the if..else..else logic, it need to be able to short circuit.
Here's a quick fix: change the interface's Execute method to return a bool to indicate whether to rule should fire and add a Value property to get the rule's decimal value. Also, add a defulat rule that alwasys evaluates true and returns zero. Then change the implementation (test) to get the value of the first rule to evaluate true:
[Test]
public void TestRulesUsingList2()
{
var rules = new IRules[]{ new RuleNumberOne(), new RuleNumberTwo(),
new DefaultRule() };
var date = new Oobject { Time = 1, Something = 1 };
var rate = rules.First(x => x.Execute(date)).Value;
Assert.That( rate, Is.EqualTo(.75m));
}
public class Oobject
{
public int Time { get; set; }
public int Something { get; set; }
}
public interface IRules
{
bool Execute(Oobject date);
decimal Value { get; }
}
public class RuleNumberOne : IRules
{
public bool Execute(Oobject date)
{
return date.Time > 0 && date.Something <= 499;
}
public decimal Value
{
get { return .75m; }
}
}
public class RuleNumberTwo : IRules
{
public bool Execute(Oobject date)
{
return date.Time >= 500 && date.Something <= 999;
}
public decimal Value
{
get { return .85m; }
}
}
public class DefaultRule : IRules
{
public bool Execute(Oobject date)
{
return true;
}
public decimal Value
{
get { return 0; }
}
}
You can go for a format and not a design-pattern in the if-else condition;
Generally, if you have lot of conditions I prefer if than lot of nested if-else's you can opt for something like this;
if(condition1){
return x; // or some operation
}
if(condition 2){
return y; // or some operation
}
return default; // if none of the case is satisfied.
I do not think this is a anti pattern Problem and for code metrics is also oki. The If is not nested and not very complex!.
But you might make better for example using Switch or you make own class which contains properties IsAgeBiggerThanMax() etc.
Switch update:
var range = (time - 1) / 499;
switch (range)
{
case 0: // 1..499
rate = 0.75;
break;
case 1: // 500.. 999
rate = 0.85;
break;
default:
rate = 0;
if (time == 1000)
{
rate = 1.0;
}
break;
}
Testing is a philosophy question we do not know what is this function and what is doing. maybe it can be tested 100% from outside!
I really like Leo Lorenzo Luis's Solution.
But instead of returning the Rate, I would let the Rule do something with it.
This will respect The S. from the S.O.L.I.D. Principles
and the Law Of Demeter.
Also, when a class "asks" for a value that is contained into another class, you can identify it as a smell called the data class. You should try to avoid this.
That being said: I would do two things to polish Leo Lorenzo's solution:
Call the right Rule without the for loop.
Executing the behavior requested inside it's associated Rule class.
In order to do this, we have to map the rule classes with their time range, so they can be accessed directly instead of having to iterate through a loop. You'll need to implement your own Map Object (or List Object, or Collection), overloading the [] operator and it's add function
so you can add your rules in your map like this for example:
ranges.Add(0,500).AddRule(rule1);
ranges.Add(500,1000).AddRule(rule2);
etc..
You can see above, there is an Object Range that can have an Object Rule associated to it. So you could eventually add more than one rule for the same Range.
Then, you call it like this:
ranges[Object.time].Execute(Object);
If you have a huge amount of "if" or if you want to put this information in a settings file then I would suggest you create a class to store this information.
Class
FromTime
ToTime
Value
values.Add(New Class(0, 499, .75));
values.Add(New Class(500, 999, .85));
values.Add(New Class(1000, 9999, 1));
Then you loop each items in the collection
if(object.Time >= curItem.FromTime && object.Time <= curItem.ToTime)
rate = curItem.Value;
You could always have nullable values or set -1 as infinite.
values.Add(New Class(-1, 0, 0));
values.Add(New Class(0, 499, .75));
values.Add(New Class(500, 999, .85));
values.Add(New Class(1000, -1, 1));
if((object.Time >= curItem.FromTime || curItem.FromTime == -1) && (object.Time <= curItem.ToTime || curItem.ToTime == -1))
rate = curItem.Value;
Just do one comparison in each if, and go top-to-bottom with the values:
if (Object.Time >= 1000)
rate = 1.0;
else
if (Object.Time >= 500)
rate = 0.85;
else
if (Object.Time > 0)
rate = 0.75;
else
rate = 0;

Get Max() of alphanumeric value

I have a dictionary containg ID which are alphanumeric (e.g. a10a10 & d10a9) from which I want the biggest ID, meaning 9 < 10 < a ...
When I use the following code, d10a9 is MAX since 9 is sorted before 10
var lsd = new Dictionary<string, string>();
lsd.Add("a", "d10a10");
lsd.Add("b", "d10a9");
string max = lsd.Max(kvp => kvp.Value);
How can I get the Max value of the IDs with the Longest string combined?
I think you may try to roll your own IComparer<string>
class HumanSortComparer : IComparer<string>
{
public int Compare(string x, string y)
{
// your human sorting logic here
}
}
Usage:
var last = collection.OrderBy(x => x.Value, new HumanSortComparer()).LastOrDefault();
if (last != null)
string max = last.Value;
this works like a charm assuming IDs always start with "d10a":
int max = lsd.Max(kvp => Convert.ToInt32(kvp.Value.Substring(4)));
Console.Write(string.Format("d10a{0}", max));
One way would be to do this
string max =lsd.Where(kvp=>kvp.Value.Length==lsd.Max(k=>k.Value.Length)).Max(kvp => kvp.Value);
however I think that this method would evalute the max length for each item so you may be better to extract it to a variable first
int maxLength=lsd.Max(kvp=>kvp.Value.Length);
string max = lsd.Where(kvp=>kvp.Value.Length == maxLength).Max(kvp => kvp.Value);
If you are going to have null strings in there you may need to perform null checks too
int maxLength=lsd.Max(kvp=>(kvp.Value??String.Empty).Length);
string max = lsd.Where(kvp=>(kvp.Value??String.Empty).Length == maxLength).Max(kvp => kvp.Value);
Alternatively treat your string as Base36 number and convert to long for the max function and then convert back again to get the max string.
string max =lsd.Max(tvp=>tvp.Value.FromBase36()).ToBase36();
public static class Base36 {
public static long FromBase36(this string src) {
return src.ToLower().Select(x=>(int)x<58 ? x-48 : x-87).Aggregate(0L,(s,x)=>s*36+x);
}
public static string ToBase36(this long src) {
StringBuilder result=new StringBuilder();
while(src>0) {
var digit=(int)(src % 36);
digit=(digit<10) ? digit+48 :digit+87;
result.Insert(0,(char)digit);
src=src / 36;
}
return result.ToString();
}
}
Finally just just the Agregate extension method instead of Max as this lets you do all the comparison logic....
lsd.Agregate(string.Empty,(a,b)=> a.Length == b.Length ? (a>b ? a:b) : (a.Length>b.Length ? a:b));
This could doesn't have null checks but you easily add them in.
I think if you did this:
var max = lsd.OrderByDescending(x => x.Value)
.GroupBy(x => x.Value.Length)
.OrderByDescending(x => x.Key)
.SelectMany(x => x)
.FirstOrDefault();
It may give you what you want.
You need StringComparer.OrdinalIgnoreCase.
Without the need to use linq, the function that do that is quite simple.
Complexity is, of course, O(n).
public static KeyValuePair<string, string> FindMax(IEnumerable<KeyValuePair<string, string>> lsd)
{
var comparer = StringComparer.OrdinalIgnoreCase;
var best = default(KeyValuePair<string, string>);
bool isFirst = true;
foreach (KeyValuePair<string, string> kvp in lsd)
{
if (isFirst || comparer.Compare(kvp.Value, best.Value) > 0)
{
isFirst = false;
best = kvp;
}
}
return best;
}
Okay - I think you need to first turn each key into a series of strings and numbers - since you need the whole number to be able to determine the comparison. Then you implement an IComparer - I've tested this with your two input strings as well as with a few others and it appears to do what you want. The performance could possibly be improved - but I was brainstorming it!
Create this class:
public class ValueChain
{
public readonly IEnumerable<object> Values;
public int ValueCount = 0;
private static readonly Regex _rx =
new Regex("((?<alpha>[a-z]+)|(?<numeric>([0-9]+)))",
RegexOptions.Compiled | RegexOptions.IgnoreCase);
public ValueChain(string valueString)
{
Values = Parse(valueString);
}
private IEnumerable<object> Parse(string valueString)
{
var matches = _rx.Matches(valueString);
ValueCount = matches.Count;
foreach (var match in matches.Cast<Match>())
{
if (match.Groups["alpha"].Success)
yield return match.Groups["alpha"].Value;
else if (match.Groups["numeric"].Success)
yield return int.Parse(match.Groups["numeric"].Value);
}
}
}
Now this comparer:
public class ValueChainComparer : IComparer<ValueChain>
{
private IComparer<string> StringComparer;
public ValueChainComparer()
: this(global::System.StringComparer.OrdinalIgnoreCase)
{
}
public ValueChainComparer(IComparer<string> stringComparer)
{
StringComparer = stringComparer;
}
#region IComparer<ValueChain> Members
public int Compare(ValueChain x, ValueChain y)
{
//todo: null checks
int comparison = 0;
foreach (var pair in x.Values.Zip
(y.Values, (xVal, yVal) => new { XVal = xVal, YVal = yVal }))
{
//types match?
if (pair.XVal.GetType().Equals(pair.YVal.GetType()))
{
if (pair.XVal is string)
comparison = StringComparer.Compare(
(string)pair.XVal, (string)pair.YVal);
else if (pair.XVal is int) //unboxing here - could be changed
comparison = Comparer<int>.Default.Compare(
(int)pair.XVal, (int)pair.YVal);
if (comparison != 0)
return comparison;
}
else //according to your rules strings are always greater than numbers.
{
if (pair.XVal is string)
return 1;
else
return -1;
}
}
if (comparison == 0) //ah yes, but were they the same length?
{
//whichever one has the most values is greater
return x.ValueCount == y.ValueCount ?
0 : x.ValueCount < y.ValueCount ? -1 : 1;
}
return comparison;
}
#endregion
}
Now you can get the max using OrderByDescending on an IEnumerable<ValueChain> and FirstOrDefault:
[TestMethod]
public void TestMethod1()
{
List<ValueChain> values = new List<ValueChain>(new []
{
new ValueChain("d10a9"),
new ValueChain("d10a10")
});
ValueChain max =
values.OrderByDescending(v => v, new ValueChainComparer()).FirstOrDefault();
}
So you can use this to sort the string values in your dictionary:
var maxKvp = lsd.OrderByDescending(kvp => new ValueChain(kvp.Value),
new ValueChainComparer()).FirstOrDefault();

C# Sort list, Logical Compare

i have the following problem
I have a list with strings for example (100_1, 100_2 .... , 100_10)
I sort the list with following code
extraImgsRaw.Sort((photo1, photo2) => photo1.CompareTo(photo2));
the result of this is : 100_1, 100_10, 100_2, 100_3 and so on
the result that I want is a logical compare like 100_1, 100_2 and then 100_10 so I prefer a
Natural numeric sort not a Alphabetic sort.
Do I need to write my own compare class that implements the ICompare interface or there is a build method in LINQ that does that?
thank you in advance
There's nothing built-in, but if the data is exactly as shown in your question then it shouldn't be too difficult to knock up a Comparison<T> to do this for you:
extraImgsRaw.Sort((x, y) =>
{
// error checking etc removed for brevity
int[] xi = x.Split('_').Select(int.Parse).ToArray();
int[] yi = y.Split('_').Select(int.Parse).ToArray();
int c = xi[0].CompareTo(yi[0]);
return (c != 0) ? c : xi[1].CompareTo(yi[1]);
});
Split and compare elements,
Here is one I wrote for 'versions'.
/// <summary>
/// Only works for version numbers in the form a ( . b ( . c ( . d )? )? )?
/// </summary>
public class VersionComponents : IComparable<VersionComponents>
{
readonly int[] components;
int[] GetComponents(string cpnumber)
{
var tokens = cpnumber.Split(".".ToCharArray(),
StringSplitOptions.RemoveEmptyEntries);
return tokens.Select(x => Convert.ToInt32(x)).ToArray();
}
public VersionComponents(string cpnumber)
{
components = GetComponents(cpnumber);
}
public int this[int index]
{
get { return components.Length > index ? components[index] : 0; }
}
public int CompareTo(VersionComponents other)
{
for (int i = 0; i < components.Length ||
i < other.components.Length; i++)
{
var diff = this[i].CompareTo(other[i]);
if (diff != 0)
{
return diff;
}
}
return 0;
}
}

Categories