Simple way to transpose data before passing to functions? - c#

This is one of the hardest questions I've ever had to title here on SO. :) Although the title might not make sense, hopefully the question itself will.
Let's say I have a data structure like a Dictionary<string, List<double>>, and that I have functions that then take List<double>s as a parameter:
Dictionary<string, List<double>> candy_positions = new Dictionary<string, List<double>>();
candy_positions.Add( "Godiva", new List<double> { 1.0, 2.0, 4.0 });
EatCandy( candy_positions["Godiva"]);
...
But now I have decided that I don't want to do it this way. I want to replace my Dictionary with a List<CandyPositions>, where CandyPositions looks something like this:
public class CandyPositions
{
public double Sees;
public double Godiva;
public double Lindt;
}
However, I really would like to leave EatCandy() alone. Obviously, the problem is now that my data doesn't lend itself to be passed directly into the method. Instead, I have to do something lame like:
List<CandyPositions> candy_positions = new List<CandyPositions>();
...
var positions = from x in candy_positions select x.Godiva;
EatCandy( positions.ToList());
every time I want to call the method. I'd prefer to be able to do this in a more simple way, like:
EatCandy( candy_positions.GetPositionsFor( "Godiva"));
where the parameter "Godiva" matches the property name in the CandyPositions class.
After writing this question, I've realized that it isn't really about transposing data -- that part of it can be handled by writing an extension method. The part I don't know how to do is to pass in a property name, so that the extension method can take this and associate it with a class's property. I don't want to pass in a string, either, mainly because this will open the door for all sorts of runtime errors. I know how to make this work by passing "Godiva" to my extension method. What I really want to pass in is something akin to CandyPositions.Godiva instead.
This question is probably a little confusing, so in summary, I would accept the best of two types of answers:
Is there a better way to deal with transposing data, than to use an extension method + some way of accessing a property name?
Is there a way to specify the property that I want my extension method to retrieve, other than by a string?
My current extension method looks like this:
public static List<double> GetPositions( this List<CandyPositions> positions, string candy_name)
{
return (from x in positions select x.GetType().GetProperty(candy_name).GetValue(x, null)).Cast<double>().ToList();
}

Well, you could use:
public static List<double> GetPositions(this List<CandyPositions> positions,
Func<CandyPositions, double> projection)
{
return positions.Select(projection).ToList();
}
and call it with:
EatCandy(candyPositions.GetPositions(x => x.Godiva));
On the other hand, if you can change EatCandy to accept an IEnumerable<double> instead, you don't need the extra method - you can just use:
EatCandy(candyPositions.Select(x => x.Godiva));
without writing an extra method at all.
EDIT: If you need to iterate over two sequences at once, there are two options:
If you're using .NET 4, you can use the Zip extension method.
Otherwise, you can basically write your own:
using (var iterator1 = sequence1.GetEnumerator())
using (var iterator2 = sequence2.GetEnumerator())
{
while (iterator1.MoveNext() && iterator2.MoveNext())
{
var value1 = iterator1.Current;
var value2 = iterator2.Current;
// Use the values here
}
}

Related

Contains method using Linq/Lambda

This method finds different dates and adds to dates array. Is it possible to make this method with linq/lambda?
public static void FindDates(DateTime[] dates, LinkedList<Letter> L, out int counter)
{
counter = 0;
foreach (var let in L)
{
if (!dates.Contains(let.Date))
{
dates[counter] = let.Date;
counter++;
}
}
}
You need to change the prototype of the method, but you can do something like:
public static IReadOnlyList<DateTime> FindDates(IEnumerable<Letter> L)
{
return L.Select(l => l.Date).Distinct().ToList();
}
The value of counter can be retrieved easily by reading the Count property of the result list.
Overall, it's a good practice to avoid side-effects in methods as much as possible. Modifying an array passed as a parameter like you do is a good way to get bitten later.
Also, since the Linq extension methods are defined on IEnumerable<T>, we can change the parameter of the method to IEnumerable<Letter>. It'll work exactly the same with your LinkedList<Letter>, with the added benefit that it won't break if later you decide to use another collection type (such as List<Letter>)

How do I refresh an array full of returned values of method calls?

In C#, I have a string array that I have written full full of "getter" method calls. They call methods in another class so that the array is populated with the needed strings. It looks something like this:
string[] mCalls = {c.get1(), c.get2(), c.get3()};
I'm sure this situation could apply to any program. However, in my program the variables these methods return are initially set with the string "Unchecked" - thus filling this example array with Unchecked 3 times. As my program goes on and things are checked, the values of the string variables get changed within the class they're in. I've been simply re-calling the getter methods at appropriate times to change what's in my array, like this:
mCalls[0] = c.get1();
mCalls[1] = c.get2();
mCalls[2] = c.get3();
I don't really like this. It seems inevitable that one day I'll have to change something, and if that happens I will have to manually do the tedious work of changing all of the indexing throughout my program. If this happens to be the best way I'm fine with that, but I assume there are better ways. So, in any case, is there a way to "refresh" the values in an array that is set up like this? And if so, what is it?
You want something like this:
public string[] MCalls
{
get
{
return new string[]{c.get1(), c.get2(), c.get3()};
}
private set;
}
and then use MCalls as if it is a regular variable whenever you want to access the arrays
You could change your array to contain functions instead of strings like this:
Func<string>[] mCalls = { c.get1, c.get2, c.get3...};
And then use it this way:
string c2 = mCalls[1]();
But note that this way every access is a method call. I'm not sure what you are really trying to achieve, there may be better overall designs than this approach.
Couple of options:
Create an array of lambdas:
var mCalls = new Func<object, string>[] {
(object o) => o.ToString() ,
(object o) => o.GetHashCode().ToString(),
(object o) => o.GetType().ToString(),
};
If the input to each lambda is the same you can create a lambda that returns an array:
Func<object, string[]> GetValues = (object o) => new string[]
{
o.ToString() ,
o.GetHashCode().ToString(),
o.GetType().ToString(),
};
Then just reload the array by calling the lambda:
mCalls = GetValues(c);
Note that it isn't technically refreshing the array, it's creating a new array. If you need to keep the array the same but just update the values you'd ned to loop through the array and assign the values by index.
What you could do is loop thorugh with reflection and get all methods from the class and from here you can get a list of method names. With this list you can assign to an array or run the methods by name or whatever. You can also filter the list to get your specific method names only:
var methodNames = typeof(MyClass).GetMethods(BindingFlags.Public | BindingFlags.Static)
.Select(x => x.Name)
.Distinct()
.OrderBy(x => x);
To call the methods:
foreach(var method in methodNames)
{
typeof(MyClass).GetMethod(method).Invoke(t, new[] { "world" });
}

Passing list members into a function

How would I pass a list of values into a function, where the values are already stored in a list and the function isn't the same every time?
To explain, I've got a list of several different types of custom objects (A List<object> to make this work) and I want to pass those objects into a function. However, the function isn't always the same. I could have several different functions, and, assuming that List's contents will always match the function's input variables, I want to be able to pass the list's contents into my function.
The following code is an example of what might work, but for one flaw:
List<object> myListOfVariables = new List<object>();
myListOfVariables.Add("Hello, world!");
myListOfVariables.Add(10);
void SayHelloXTimes(string helloString, int x) {
for(int i = 0;i<x;i++) {
print(helloString)
}
}
SayHelloXTimes(myListOfVariables[0], myListOfVariables[1]);
Now, since I know my list will always contain the right amount of variables in the right positions, that would work, if I only had one function. But the problem is, I need to expand this so I could take apart my list and pass it into functions with different amounts of parameters.
For other reasons, I know my list will always have the right amount of variables in the right positions, so we don't need to worry about that. I'll also know the name of the function I need to pass my values into. I suppose I could do a load of if statements depending on the length of my list, like this:
if (myListOfVariables.Length == 2) {
SayHelloXTimes(myListOfVariables[0], myListOfVariables[1]);
}
else if (myListOfVariables.Length == 3) {
SayHelloXTimesForY(myListOfVariables[0], myListOfVariables[1], myListOfVariables[2]);
}
However, this (obviously) is really clunky code and I'd like to avoid it at all costs. Is there another solution to my problem? I know this is really confusing, but I did my best to explain it. If you're still confused as to what I'm trying to do, please let me know.
And no, this is not a homework problem. ;)
I think want you want to do can be done using reflection. Look at MethodBase.Invoke Method
All you have to do is add all the parameters in the order the function expects to an object array.
class Program
{
public static void SayHelloXTimes(string helloString, int x)
{
for (int i = 0; i < x; i++)
{
Console.WriteLine(helloString);
}
}
static void Main(string[] args)
{
MethodInfo Method = typeof(Program).GetMethod("SayHelloXTimes");
Method.Invoke(null, new object[] { "foo", 3 });
Console.ReadLine();
}
}
You want params:
void SayHelloXTimes(params string[] list) {
for(int i = 0;i<list.Length;i++) {
print(list[i])
}
}
SayHelloXTimes("Hi", "Hi", "Hi"); // legal
SayHelloXTimes("Hi"); // legal
SayHelloXTimes("Hi", "Hi", "Hi", "Hi", "Hi", "Hi"); // still legal
If this were my application, I would create a parameter class to hold the list values.
You could pass the list into the class' constructor and either extract it into class-local properties (since you know the positions) or you could expose the values as readonly property directly from the list.
You can then just pass an instance of the parameter class to each of the methods and not have to worry about the number of parameters to the methods.

Evaluating a set of rules defined in a string

I made a system that creates a simple string with Function/Response format, example:
Check('Value'):ShowImage(#)|Check('Value'):OtherFunction(#)....and so on
Where Check is the name of a function, Value is the parameter, ShowImage is the name of a Response function, # is the entry paremeter (result of the previous function). The pipe splits another Function/Response pair that fires if the first Check('Value') function once "checked" were not satisfied (say, if the parameter was not accomplished the Check condition the function is invalid and hence the Response part in the first Function/Response pair is not executed, so system keep trying Functions awaiting to find the one that executes the right Response).
The way the application should work is to evaluate each rule (similar to a JavaScript eval function) and take appropriate action based on function results.
At first glance, it looks complicated, because first of all I need to cast the string to the right real C# function that will actually process the condition. Therefore, depending on the function result, decide where to point to execute my Response function.
Furthermore: This is just the kind example, because there are functions as * that represent something like: "any condition is true" what in almost all cases this function is the last in the chain (the default function).
That's my problem, I can't realize what is the easiest way to cope with this problem.
Maybe a chain of delegates? Lambdas? Anonymous stored into a structure...
Could you give me your measure/advise? Where to start?
Depending on the level of extensibility you want to have, I would say the most extensible way would be to use reflection to get method references, after you have parsed the input string.
You can start by splitting your problem into smaller subproblems.
Let's say you are aiming for something like this:
static void Main(string[] args)
{
string rules =
"Check(Morning):Say(Good morning)|" +
"Check(Afternoon):Say(Good afternoon)|" +
"Check(Evening):Say(Good night)";
// next, you need some **object instances** which will
// provide a context for your "test" and "action" methods.
// you don't want to use static methods if you
// went through the pain of defining such an architecture!
// let's say that a "Tester" object has a "Check" method,
// and an "Executor" object has a "Say" method:
var tester = new Tester("Afternoon");
var executor = new Executor();
// since I suck at regular expressions,
// I am using plain string methods to split
// the expression into tokens. You might want
// to add some validation
foreach (var rule in rules.Split('|'))
{
var result = Parse(rule, tester, executor);
if (result.TestPassed)
{
result.Execute();
break;
}
}
}
A "result" as it's used above would then have an interface like this:
public interface IResult
{
// returns true if a test is fulfilled
bool TestPassed { get; }
// executes the related action
void Execute();
}
And, if you want to delegate actual actions to some unknown methods, a reasonable way to implement it would be something like this:
public class Result : IResult
{
#region IResult Members
private readonly Func<bool> _testMethod;
public bool TestPassed
{
get { return _testMethod(); }
}
private readonly Action _actionMethod;
public void Execute()
{
_actionMethod();
}
#endregion
public Result(Func<bool> testMethod, Action actionMethod)
{
_testMethod = testMethod;
_actionMethod = actionMethod;
}
}
What's left is to use some reflection to get the actual methods out of your strings:
private static IResult Parse(string rule, object tester, object executor)
{
// split into test/action
var tokens = rule.Split(':');
// extract the method/parameter part for each expression
var test = GetMethodAndParams(tokens[0]);
var action = GetMethodAndParams(tokens[1]);
// use reflection to find actual methods
var testMethod = tester.GetType().GetMethod(test.Method);
var actionMethod = executor.GetType().GetMethod(action.Method);
// return delegates which will simply invoke these methods
return new Result
(
() => (bool)testMethod.Invoke(tester, new object[] { test.Param }),
() => actionMethod.Invoke(executor, new object[] { action.Param })
);
}
That is, more or less, your program's skeleton. You should be able to fill in the missing parts yourself, as an exercise. If you have problems, I can update the answer later.
A GetMethodAndParams method should split the input string into a Tuple (or your custom class) which contains the method name and its params as plain strings. Tester and Executor classes can also be implemented trivially.
It looks like you want a pattern along the lines of the .NET TryParse() methods. In that case, you would modify your check method to have an out parameter that is the value (represented in your example by #).
int result;
if(Check('Value', out result))
ShowImage(result);
else(Check('Value2', out result))
OtherFunction(result);
Finally I'm back here to post what I've done few weeks ago to solve this situation.
It was easy.
Regex class provide few options, one of those is "Explicit Catpure", all streams with the form (?) can be handled as strong typed parameters so, if the named group "IsNotEmptyorNull" then the function is present and it is promotable to casting using the form Enum.Parse("").
Snipet:
Regex rx = new Regex(#"(?<function>Check|BooleanOp)\('(?<param>[\w]+)'\){1}:(?<action>[\w]+){1}", RegexOptions.ExplicitCapture);
Match m;
Dictionary<FunctionArray, String> actions = new Dictionary<FunctionArray, String>();
if((m=rx.Match(strStream)).Success)
{
actions.Add((FunctionArray)Enum.Parse(typeof(FunctionArray), m.Groups["function"].value, true), m.Groups["param"].value);
}
Of course, there are lost the action part so I've improved the Dictionary stuff with an specialized Struct that can handle the functions and values as a source for decision taking.
Thanks to all. Ed.

Cast from filtered custom List<T> with LINQ

I have a custom list which inherits from Generic.List<T> like this:
public class TransferFileList<T> : List<TransferFile> { .. }
When I set (where 'Files' is a TransferFileList<T>):
var files = uploadResponse.Files.Where(x => !x.Success).ToList()
the 'files' object resolves as System.Collections.Generic.List<TransferFile>, not TransferFileList<T>, which is what I would expect as it was what was being filtered through the Where, so how could I successfully return a list of TransferFileList<T> into 'files'?
I did try:
var files = uploadResponse.Files.Where(x => !x.Success).ToList()
as TransferFileList<TransferFile>;
but using that safe cast, it just resolves as null.
Thanks guys and gals.
First, I have to ask why you are inheriting from List<T>? 99% of the time that's a bad idea.
If you want to extend the functionality of a list, use extension methods:
public static something PrintErrors(this List<TransferFile> list)
{
//do your printing logic
}
On to the answer: ToList() operates on an IEnumerable<T> and converts the members of the sequence to a List of the same type. Since you inherit from List<T> which implements IEnumerable<T>, that's what happens there.
Where() works the same way - operates on an IEnumerable<T> and returns an IEnumerable<T>.
To get some arbitrary list-like object back, like you have, you need to add the items in a sequence to your custom list, like so:
var myFiles = new TransferFileList<TransferFile>();
myFiles.AddRange(originalFileList.Where(condition));
You can add an extension method for IEnumerable<TransferFile> to handle that scenario:
public static TransferFileList ToTransferFileList(
this IEnumerable<TransferFile> files)
{
return new TransferFileList(files);
}
// ...
var files = uploadResponse.Files.Where(x => !x.Success).ToTransferFileList();
This provides you with the TransferFileList instead of just a List<TransferFile>. Note the reason your as returns null is because while TransferFileList is a List<TransferFile>, the same does not hold in the other direction. That is, your List<TransferFile> is NOT a TransferFileList object.
I agree with #RexM that any attempt at subclassing List<T> be avoided due to the multitude of pitfalls associated. I suggest Composition (Has-A rather than Is-A) or sticking with the base class library collections instead.
Thanks guys.
I like SLV's extension approach, but is there any other straight casting approach?
If not I might just go with the reverted in-line approach I was hoping to avoid:
var transferFiles = new TransferFileList<TransferFile>();
if (files != null)
transferFiles.AddRange(files);

Categories