equivalent to list() of php in C# - c#

there some method equal list() of php in C#?
usage list() in PHP:
$array = array('foo','baa');
list($foo, $baa) = $array;
echo $foo; //foo
echo $baa; //baa
equivalent in javascript:
var arr = ['foo','baa'];
var foo;
var baa;
[foo, baa] = arr;
Thanks in advance!

There is no direct language equivalent in C#. While collection initializers can be used to construct the array, there is no way to extract elements directly.
This requires explicitly setting variables, ie:
var theArray = GetArrayFromSomewhere();
var foo = theArray[0];
var bar = theArray[1];

This is more similar to the original intention, though some might not like all the ceremony :
string a = null, b = null, c = null;
new ValList(v => a = v,
v => b = v,
v => c = v).SetFrom(new string[] { "foo", "bar" });
//here a is "foo", b will be "bar", and c is still null
And the simple helper class:
class ValList
{
private Action<string>[] _setters;
public ValList(params Action<string>[] refs)
{
_setters = refs;
}
internal void SetFrom(string[] values)
{
for (int i = 0; i < values.Length && i < _setters.Length; i++)
_setters[i](values[i]);
}
}

One way to do the original php (I know nothing about PHP) task in C# would be
List<string> name_list = new List<string>{"transmogrify","untransmogrify"};
name_list.ForEach(x => Debug.WriteLine(x));
Which leads to the more general observation, that C# allows you to do a lot while leaving the variables in the array or list. LINQ in particular makes doing many things quite simple. So if you are looking for a way to replicate some PHP code in C# I would think in those terms. Just one parting example, if you had an array of ints you wanted to sum you could do this
int[] some_ints = {1, 2, 3, 4};
int sum += some_ints.Sum();

As Reed said ,
There is no direct language equivalent in C#.
But you can create it like below ↓
class Program
{
static void Main(string[] args)
{
string[] tmp = new string[] { "foo", "baa" };
string foo, baa;
tmp.Go(out foo, out baa);
Console.WriteLine(foo);
Console.WriteLine(baa);
Console.ReadKey();
}
}
public static class PHPList
{
public static void Go(this string[] soruce, out string p1, out string p2)
{
p1 = soruce[0] + "";
p2 = soruce[1] + "";
}
}

Just piggy-backing #Yoni's answer into an extension method. This was a cute and silly exercise; however, as has been pointed out in comments and answers, some language features simply do not port from one language to another.
In PHP, list($a, $b) = $c constitutes an assignment, and since no variable declarations are required (the list() is the declaration) it can provide terse and clean assignment syntax.
In C# however, since variable declarations are required prior to usage, you're better off simply assigning the value off the list at that time, as the following example will show.
Speaking of, incoming example:
public static void Into<TSource>(this IEnumerable<TSource> source,
params Action<TSource>[] actions)
{
if (ReferenceEquals(source, null)) {
throw new ArgumentNullException("source");
}
if (ReferenceEquals(actions, null)) {
throw new ArgumentNullException("actions");
}
foreach (var assignment in actions.Zip(source, (action, item) => new {
Action = action,
Item = item,
})) {
assignment.Action.Invoke(assignment.Item);
}
}
So you can simply collection.Into(o => a = o, o => ...); for example:
var numbers = new[] { 1, 2, 3, 4, 5 };
int a = 0, b = 0, c = 0, d = 0;
int e = 0, f = 0, g = 0, h = 0, i = 0, j = 0;
numbers.Into(o => a = o,
o => b = o,
o => c = o,
o => d = o);
numbers.Into(o => e = o,
o => f = o,
o => g = o,
o => h = o,
o => i = o,
o => j = o);
This will yield:
Console.WriteLine(a); // 1
Console.WriteLine(b); // 2
Console.WriteLine(c); // 3
Console.WriteLine(d); // 4
Console.WriteLine(e); // 1
Console.WriteLine(f); // 2
Console.WriteLine(g); // 3
Console.WriteLine(h); // 4
Console.WriteLine(i); // 5
Console.WriteLine(j); // 0
Perhaps some Expression<> magic can shorten it to:
numbers.Into(o => a,
o => b,
... )

Related

How dynamically group by and compute aggregate sums/maximums data with LINQ in c#

We have an API to work with data that comes from different sources (database, webservices, plain text,...) so we store it in a List structure.
We have this code to select some columns of them and apply functions to obtain new data (as sum two columns,...)
Func<dynamic[], object>[] leftFunctions = new Func<dynamic[], object>[this.Columns.Count];
IEnumerable<dynamic[]> returnValue = null
j = 0;
foreach (JoinDataColumn dataColum in this.Columns.OrderBy(x => x.Index))
{
//Obtenemos para cada columna la funcion
leftFunctions[j++] = dataColum.getLeftFunction(LeftDataQuery);
}
returnValue = (await LeftDataQuery.ExecuteAsync(parameters))
.Select(x => leftFunctions.Select(f => f.Invoke(x)).ToArray());
In the above code: LeftDataquery is a class to obtain the list with data executing this, and returning List<object[]>
await LeftDataQuery.ExecuteAsync(parameters)
LeftFuncions are formulas to create new data from source data, "lefdataquery[1]+lefdataquery[2]" or simply "lefdataquery[0]" to obtain the data of the first column.
In the JoinDataColumn class I have a description of each column of the result List: name, type, and the agregate function.
At the end, the user can select the columns to group by and the agregation formula to the others ones (sum,max,min,count distinct,...). So now I have the returnvalue with a subset of columns of the original source and a list of index with the columns to group by and a list of indexes with their agregation formula (for example the index 1 is a SUM and so on)
public enum DataColumnAggregation { NONE = 0, SUM = 1, MAX = 2, MIN = 3 }
Any idea on how to group by this data and get the SUM/MAX/MIN,..
Doing some test I've wrote this code, but the problem is that the Groupby doesn't work with an object array as parameter. Any idea to have GroupBy working with this aproach?¿
public enum DataColumnAggregation { NONE = 0, SUM = 1, MAX = 2, MIN = 3 }
static void Main(string[] args)
{
List<object[]> returnValue = new List<object[]> { new object[] { "C1", 1, 2 }, new object[] { "C2", 3, 4 }, new object[] { "C1", 1, 3 } };
DataColumnAggregation[] config = new DataColumnAggregation[] { DataColumnAggregation.NONE, DataColumnAggregation.SUM, DataColumnAggregation.MAX };
//TODO agregar por la columna 0 , sumar la columna 1 y maximo de la columna 2 de returnvalue
var resultado2 = returnValue.GroupBy(x => getGroupByColumns(x,config)).Select(x=>agregar(x, config));
}
private static object[] agregar(IGrouping<string[], object[]> x, DataColumnAggregation[] config)
{
List<object> result = new List<object>();
for (int i = 0; i < config.Length; i++)
{
if (config[i] == DataColumnAggregation.NONE)
{
result.Add(x.Select(xy => xy[i]).FirstOrDefault());
}
if (config[i] == DataColumnAggregation.SUM)
{
result.Add(x.Sum(xy => Convert.ToInt32(xy[i])));
}
if (config[i] == DataColumnAggregation.MAX)
{
result.Add(x.Max(xy => xy[i]));
}
if (config[i] == DataColumnAggregation.MIN)
{
result.Add(x.Min(xy => xy[i]));
}
}
return result.ToArray();
}
private static string[] getGroupByColumns(object[] x, DataColumnAggregation[] config)
{
List<string> group = new List<string>();
for (int i = 0; i< config.Length; i++)
{
if (config[i] == DataColumnAggregation.NONE) group.Add(x[i].ToString());
}
return group.ToArray();
}
Thanks
Since you are attempting to group by string[] (or better, List<string>), you need an IEqualityComparer to pass to GroupBy that compares the elements.
public class IEnumerableSequenceEqualityComparer<T> : IEqualityComparer<IEnumerable<T>> {
public bool Equals(IEnumerable<T> x, IEnumerable<T> y) =>
Object.ReferenceEquals(x, y) || (x != null && y != null && (x.SequenceEqual(y)));
public int GetHashCode(IEnumerable<T> src) {
// Will not throw an OverflowException
//unchecked {
// return src.Where(e => e != null).Select(e => e.GetHashCode()).Aggregate(17, (a, b) => 23 * a + b);
//}
var hc = new HashCode();
foreach (var v in src)
hc.Add(v);
return hc.ToHashCode();
}
}
A factory class named Make helps create the comparer:
public static class Make {
public static IEqualityComparer<IEnumerable<T>> SequenceEqualityComparer<T>() => new IEnumerableSequenceEqualityComparer<T>();
public static IEqualityComparer<IEnumerable<T>> SequenceEqualityComparer<T>(T _) => new IEnumerableSequenceEqualityComparer<T>();
}
Now you can call GroupBy with the sequence equality comparer:
var resultado2 = returnValue.GroupBy(x => getGroupByColumns(x,config), Make.SequenceEqualityComparer<string>()).Select(x=>agregar(x, config));
NOTE: This causes the group Key to be IEnumerable<string>. If you prefer IList<string>, just replace IEnumerable with IList in the equality comparer class and the factor class. Or add an additional IList version with appropriate name changes.

How to get input and return type of delegate stored in list<dynamic> in c#?

I want to create list of method. and run this list of method in order.
The input of next method is output of current method.
So, this is my code for these, and i need to get input, output type.
static void Main( string [ ] args )
{
List<dynamic> temp = new List<dynamic>();
Func<int,int> fn1 = new Func<int,int>( x => 3);
Func<int,int> fn2 = new Func<int,int>(x => x + 3);
Func<int,int> fn3 = new Func<int,int>(x => x + 30);
Func<int,double> fn4 = new Func<int,double>(x => x*0.2);
temp.Add( fn1 );
temp.Add( fn2 );
temp.Add( fn3 );
temp.Add( fn4 );
int input = 6;
// use for or foreach or something
// output ?
}
Yes, you can use foreach, and call Invoke dynamically - you'll need the input to be dynamic as well though:
using System;
using System.Collections.Generic;
class Test
{
static void Main()
{
Func<int,int> fn1 = new Func<int,int>(x => 3);
Func<int,int> fn2 = new Func<int,int>(x => x + 3);
Func<int,int> fn3 = new Func<int,int>(x => x + 30);
Func<int,double> fn4 = new Func<int,double>(x => x * 0.2);
List<dynamic> pipeline = new List<dynamic> { fn1, fn2, fn3, fn4 };
dynamic current = 6;
foreach (dynamic stage in pipeline)
{
// current = stage(current) would work too, but I think it's less clear
current = stage.Invoke(current);
}
Console.WriteLine($"Result: {current}");
}
}
(It's odd that your first function ignores the input, by the way.)
Note that there's no compile-time type safety here - if one of your functions actually required a string, you'd only find out at execution time. Without knowing how you're creating the delegates in your real code, it's hard to know exactly the best way to fix this, but here's one option:
class Pipeline<TInput, TOutput>
{
private readonly Func<TInput, TOutput> function;
public Pipeline(Func<TInput, TOutput> function)
{
this.function = function;
}
public Pipeline<TInput, TNext> Then<TNext>(Func<TOutput, TNext> nextFunction) =>
new Pipeline<TInput, TNext>(input => nextFunction(function(input)));
public TOutput Process(TInput input) => function(input);
}
class Test
{
static void Main()
{
Pipeline<int, double> pipeline = new Pipeline<int, int>(x => 3)
.Then(x => x + 3)
.Then(x => x + 30)
.Then(x => x * 0.2);
var result = pipeline.Process(6);
Console.WriteLine($"Result: {result}");
}
}

Cast Int Array to Enum Flags

I have the following enum with flags:
[Flags]
public enum DataFiat {
Public = 1,
Listed = 2,
Client = 4
} // DataFiat
And I have an int array, for example:
int[] selected = new int[] { 1, 4 }
How can I convert this to my enum which would become:
DataFiat.Public | DataFiat.Client
Thank You,
Miguel
var f = (DataFiat)selected.Sum();
How about something like
var tt = (DataFiat)selected.Aggregate((i, t) => i | t);
this snippet:
var intArr = new[] { 1, 4 };
var sum = intArr.Sum(x => x);
var result = (Test)sum;
returns
DataFlat result = (DataFlat) 0;
foreach (var value in selected)
{
result |= (DataFlat)value;
}
Or if you want to use LINQ
DataFlat result = (DataFlat) selected.Aggregate(0, (old, current) => old | current);
You mean this?
IEnumerable<DataFiat> selectedDataFiats = selected.Cast<DataFiat>();
This sinmply casts each int to DataFiat.
You can't just cast the array, if it's really an object[]. You can create a new array pretty easily though:
var enumArray = originalArray.Cast<DataFiat>().ToArray();
If it were actually an int[] array to start with, you could cast - although you'd have to talk nicely to the C# compiler first:
using System;
class Program
{
enum Foo
{
Bar = 1,
Baz = 2
}
static void Main()
{
int[] ints = new int[] { 1, 2 };
Foo[] foos = (Foo[]) (object) ints;
foreach (var foo in foos)
{
Console.WriteLine(foo);
}
}
}
The C# compiler doesn't believe that there's a conversion from int[] to Foo[] (and there isn't, within the rules of C#)... but the CLR is fine with this conversion, so as long as you can persuade the C# compiler to play along (by casting to object first) it's fine.
This doesn't work when the original array is really an object[] though.
Hope this helps..

substring value from string

I have a string variable that contain [l=9;f=0;r=5;p=2]. There are may be a more than one:[l=9;f=0;r=5;p=2],[l=9;f=0;r=6;p=2].
I want to get List of Tuple<int,int,int>, where item1 = value of l, item2= value of r, item3=value of p. What is best approach to do this?
My code:
// split string
var splittedFormatedSeats = Regex.Matches(formatSeats, #"\[.+?\]")
.Cast<Match>()
.Select(m => m.Value)
.ToList();
IList<Tuple<int,int,int>> fullSeat = new List<Tuple<int, int, int>>();
foreach (var splittedFormatedSeat in splittedFormatedSeats)
{
...
}
Thanks.
I would adopt another strategy. First, split subcomponents of your string
var components = formatSeats.Split(',');
This will give you an array of string. This will be far more efficient to parse small chunks of strings instead of a big string.
You can then use either a Regex to extract the values or a simple code like this :
foreach(var component in components)
{
var parts = component.Trim("[]".ToCharArray()).Split(';');
}
var results = from component in components
let c = component.Trim("[]".ToCharArray())
.Split(';')
.Select(c=>int.Parse(c.SubString(2))
select new { l = c[0], f=c[1], r=c[2], p = c[3] };
This will produces an enumeration of an anonymous type.
foreach(var x in results)
{
Console.WriteLine("{0} / {1} / {2} / {3}", x.l, x.f, x.r, x.p);
}
If you actually need a Tuple simply change the code to :
var results = from component in components
let c = component.Trim("[]".ToCharArray())
.Split(';')
.Select(c=>int.Parse(c.SubString(2))
select new Tuple<int,int,int,int>{ l = c[0], f=c[1], r=c[2], p = c[3] };
I would however, advocate for writing a small struct to simplify the code and raise its readability.
public struct MyValue
{
private readonly int m_L;
public int L { get {return m_L; } }
private readonly int m_F;
public int F { get {return m_F; } }
private readonly int m_R;
public int R { get {return m_R; } }
private readonly int m_P;
public int P { get {return m_P; } }
public MyValue(int l, int f, int r, int p)
{
m_L = l;
m_F = f;
m_R = r;
m_P = p;
}
}
....
var results = from component in components
 let c = component.Trim("[]".ToCharArray())
  .Split(';')
  .Select(c=>int.Parse(c.SubString(2))
 select new MyValue(c[0],c[1],c[2],c[3]);
Finally, if the string always have this form, you could avoid using the Regex.
string formattedString = "[l=9;f=0;r=5;p=2],[l=9;f=0;r=6;p=2]";
var splitString = formattedString.Split(',')
.Select(p => p.Trim(new char[]{'[',']',' '}));
List<Tuple<int, int, int, int>> tupleList = new List<Tuple<int, int, int, int>>();
foreach (var item in splitString)
{
int[] finalSplit = item.Split(';').Select(p =>
Convert.ToInt32(p.Substring(p.LastIndexOf('=')+1).Trim())
).ToArray();
tupleList.Add(new Tuple<int, int, int, int>(finalSplit[0], finalSplit[1],
finalSplit[2], finalSplit[3]));
}
This will split values of l, f, r and p and add them to the Tuple.
Is the format of your inner string always the same ?
Is it always a single digit value for each variable (l, f, r & p)?
If so you can just substring them out.
foreach(var splittedFormatedSeat in splittedFormatedSeats)
{
int x, y, z;
string s = splittedFormatedSeat .ToString();
if(int.TryParse(s[3].ToString(), out x) &&
int.TryParse(s[11].ToString(), out y) &&
int.TryParse(s[15].ToString(), out z))
fullSeat.Add(new Tuple<int,int,int>(x,y,z));
}

print name of the variable in c#

i have a statement
int A = 10,B=6,C=5;
and i want to write a print function such that i pass the int variable to it and
it prints me the variable name and the value.
eg if i call print(A)
it must return "A: 10", and print (B) then it must return "B:6"
in short i want to know how can i access the name of the variable and print it to string in c#. DO i have to use reflection?
After reading the answers
Hi all, thanks for the suggestions provided. I shall try them out, however i wanted to know if it is at all possible in .NET 2.0? Nothing similar to
#define prt(x) std::cout << #x " = '" << x << "'" << std::endl;
macro which is there in C/C++?
The only sensible way to do this would be to use the Expression API; but that changes the code yet further...
static void Main() {
int A = 10, B = 6, C = 5;
Print(() => A);
}
static void Print<T>(Expression<Func<T>> expression) {
Console.WriteLine("{0}={1}",
((MemberExpression)expression.Body).Member.Name,
expression.Compile()());
}
Note: if this is for debugging purposes, be sure to add [Conditional("DEBUG")] to the method, as using a variable in this way changes the nature of the code in subtle ways.
You can use lambda expressions:
static void Main( string[] args ) {
int A = 50, B = 30, C = 17;
Print( () => A );
Print( () => B );
Print( () => C );
}
static void Print<T>( System.Linq.Expressions.Expression<Func<T>> input ) {
System.Linq.Expressions.LambdaExpression lambda = (System.Linq.Expressions.LambdaExpression)input;
System.Linq.Expressions.MemberExpression member = (System.Linq.Expressions.MemberExpression)lambda.Body;
var result = input.Compile()();
Console.WriteLine( "{0}: {1}", member.Member.Name, result );
}
This is not possible without some 'help' from the call site; even reflection does not know about names of local variables.
This is not possible to do with reflection (see Brian and Joel). In general this is not possible simply because you cannot guarantee a named value is being passed to your print function. For instance, I could just as easily do the following
print(42);
print(A + 42);
Neither of these expressions actually has a name. What would you expect to print here?
Another solution (from a closed post):
Inspired by Jon Skeet's post about Null Reference exception handling and suddenly being reminded about projection there is a way to kinda do that.
Here is complete working codez:
public static class ObjectExtensions {
public static string GetVariableName<T>(this T obj) {
System.Reflection.PropertyInfo[] objGetTypeGetProperties = obj.GetType().GetProperties();
if(objGetTypeGetProperties.Length == 1)
return objGetTypeGetProperties[0].Name;
else
throw new ArgumentException("object must contain one property");
}
}
class Program {
static void Main(string[] args) {
string strName = "sdsd";
Console.WriteLine(new {strName}.GetVariableName());
int intName = 2343;
Console.WriteLine(new { intName }.GetVariableName());
}
}
If you need to support more types than int, use the Expression API but avoid generics and handle the different expression gracefully:
private static string ToDebugOutput(params Expression<Func<object>>[] variables)
{
var sb = new StringBuilder();
foreach (var input in variables)
{
string name;
if (input.Body is UnaryExpression unary && unary.Operand is MemberExpression operand)
{
name = operand.Member.Name;
}
else if (input.Body is MemberExpression member)
{
name = member.Member.Name;
}
else
{
throw new NotSupportedException($"typeof lambda: {input.Body.GetType()}");
}
var result = input.Compile()();
sb.Append($"{name}={result}, ");
}
return sb.ToString();
}
Usage:
string s = "123";
double d = 1.23;
int i2 = 123;
var out2 = ToDebugOutput(() => s, () => d, () => i2);
// out2 = "s=123, d=1.23, i2=123, "

Categories