Say I have a
List<double[]> x = new List<double[]>();
double[] item = new double[] {1.0,2.0,3.0};
x.add(item);
etc...
Is there a faster/cleaner way to get this into a double[,] then looping it:
double[,] arr = new double[x.Count,3];
for (row = 0; row < x.Count; row++)
{
for (col = 0; col < 3; col++)
arr[row,col] = x[row][col];
}
Thanks.
No, there isn't.
Multi-dimensional arrays are strange beasts and are not widely accepted or used in the BCL.
They're also slow and should be avoided where possible.
Because I felt like it, I solved this using LINQ, however, it's hardly any cleaner. In fact, I'd argue it's less clear, but it'd danm neat :)
// Input
List<double[]> a = new List<double[]>() {
new double[]{ 1.0, 2.0, 3.0 },
new double[]{ 4.0, 5.0, 6.0 },
new double[]{ 7.0, 8.0, 9.0 }
};
// Output
var b = a.Select((item, index) => new
{
Items = item.Select((inner, inIndex) => new { Inner = inner, Y = inIndex }),
X = index
})
.SelectMany(item => item.Items, (i, inner) => new { Value = inner.Inner, X = i.X, Y = inner.Y })
.Aggregate(new double[a.Count, a.Max(aa => aa.Length)], (acc, item) => { acc[item.X, item.Y] = item.Value; return acc; })
Note: This also works for arbitrarily sized inner double[] arrays, but there will be empty spots.
So yes, there's another way of doing it, but it's not a better way :)
There is always the var_export function?
Related
I have a two dimensional array namely States. I create a one dimensional array, say SubState. Then I change SubState. I want to find new SubState in States and get the index. As an example:
int[][] States = new int[3][] { new int[] { 3, 3, 4 }, new int[] { 2, 5, 1 }, new int[] { 2, 3, 4 } };
int[] SubState = new int[States[0].Length];
States[0].CopyTo(SubState, 0);
SubState[0] -= 1;
I want to find the index of new SubState in State, which will be 2 in the example.
Thanks.
You're looking for SequenceEqual:
int index = -1;
for (int i = 0; i < States.Length; i++)
if (States[i].SequenceEqual(SubState))
{
index = i;
break;
}
If you define a LINQ FindIndex operator, you can express it more concisely using:
int index = States.FindIndex(s => s.SequenceEqual(SubState));
You can use SequenceEqual method inside a LINQ query, like this:
var nextStateIndex = States
.Select((a, i) => new {Index = i, Array = a})
.FirstOrDefault(p => p.Array.SequenceEqual(SubState))
?.Index;
if (nextStateIndex.HasValue) {
...
}
Note: this code uses the new ?. operator. If you are targeting C# version that does not have support for this operator, store FirstOrDefault result for an explicit null checking.
You can use Linq:
var index = -1;
var foundSubState = States.FirstOrDefault(x => {
index++;
return x.SequenceEqual(SubState);
});
var res = foundSubState != default(Array) ? index : -1;
I'm trying to convert a DataTable's rows into multidimensional array:
DataTable DT = new DataTable();
DT.Columns.AddRange
(
new DataColumn[]
{
new DataColumn("LA_ID"),
new DataColumn("contractid")
}
);
for(int i=1000; i<=1100; i++)
DT.Rows.Add(i, i);
EnumerableRowCollection<DataRow> appsEnum = DT.AsEnumerable();
int[,] apps = appsEnum.
Where(x => x.Field<int>("LA_ID") > 1050).
Select(x => x.Field<int>("LA_ID"), x.Field<int>("contractid")).
--Error Here-------------------------------------^
ToArray();
Can anyone help plz.
There is no version of .ToArray() that supports more than 1 dimension. You will need a for-loop here.
It could probably work with a int[][] but not for int[,]
the best you can get with ToArray() method is jagged array
int [][] apps = appsEnum.
Where(x => x.Field<int>("laid") > 1050).
Select(x => new int[] {x.Field<int>("LA_ID"), x.Field<int>("contractid")}).
ToArray();
consider another approach
DataRow[] rows = DT.Select("laid > 1050");
int[,] apps = new int[rows.Length, 2];
for(int r=0; r<rows.Length; r++)
{
apps[r,0] = rows[r].Field<int>("LA_ID");
apps[r,1] = rows[r].Field<int>("contractid");
}
This is 2D array:
int[][] array2D = new int[7][];
for (int i = 0; i < 7; i++)
array2D[i] = new int[7];
How can I turn the following into a LINQ query, or use enumerable methods to achieve the same output?
var lst = new List<Point>();
for (int r = 0; r < array2D.Length; r++)
for (int c = 0; c < array2D[r].Length; c++)
if (array2D[r][c] == 0)
lst.Add(new Point(c, r));
EDIT - Solution based on #'King King's answer
var lst = m_boardArr.SelectMany((row, rowIndex) =>
row.Select((val, colIndex) =>
new { val, point = new Point(colIndex, rowIndex) })
.Where(col => col.val == 0)
.Select(col => col.point)).ToList();
Try this:
var lst = array2D.SelectMany((x,r) => x.Select((a,c)=> new {a,b=new Point(c,r)})
.Where(a=>a.a==0)
.Select(a=>a.b)).ToList();
The trick is to use the Select and SelectMany that capture the loop variables into an anonymous type, then get those properties back later after the Where clause, thus:
var list = array2D
.SelectMany((row, r) => row
.Select((el, c) =>
new {Element = el, ColIndex = c, RowIndex = r})
.Where(thing => thing.Element == 0)
.Select(thing => new Point(thing.RowIndex, thing.ColIndex)))
.ToList();
EDIT: Bartosz's comment applies to this solution as well. Unreadable!
var lst = array2D
.SelectMany((innerArray, r)
=> Enumerable
.Range(0, innerArray.Length)
.Where(c => innerArray[c] == 0)
.Select(c => new Point(c, r)))
.ToList();
However, your current solution is more readable.
I have a list that contains 8 elements:
ConfigFile.ControllerList
this list is type of:
List<Controller>
How can i add Controllers from ControllerList to 3 dictionary keys. Dictionary is like:
Dictionary<int, List<Controller>> ControllerDictionary = new Dictionary<int, List<Controller>>();
I want to add first 3 controllers to dictionary key 0, then want to add next 3 controllers to dictionary key 1 and lastly want to add last 2 controllers to dictionary key 2. How can i do that?
You can use / to split the list into sub-list:
var ControllerDictionary = ControllerList
.Select((c, i) => new { Controller = c, Index = i })
.GroupBy(x => x.Index / maxGroupSize)
.Select((g, i) => new { GroupIndex = i, Group = g })
.ToDictionary(x => x.GroupIndex, x => x.Group.Select(xx => xx.Controller).ToList());
The idea is to first group the elements by indexes, then divide them by an int maxGroupSize(in your case 3). Then convert each group to a list.
Not sure if there's a more elegant solution, but something like this should work:
var dict = new Dictionary<int, List<Controller>>();
int x = 0;
while (x < controllerList.Count)
{
var newList = new List<Controller> { controllerList[x++] };
for (int y = 0; y < 2; y++) // execute twice
if (x < controllerList.Count)
newList.Add(controllerList[x++]);
dict.Add(dict.Count, newList);
}
To make it more general, you could also create newList empty to start, and then change y < 2 to y < GROUP_SIZE where GROUP_SIZE is whatever sized groups you want. Could even then extract this to an extension method:
public static Dictionary<int, List<T>> ToGroupedDictionary<T>
(this IList<T> pList, int pGroupSize)
{
var dict = new Dictionary<int, List<T>>();
int x = 0;
while (x < pList.Count)
{
var newList = new List<T>();
for (int y = 0; y < pGroupSize && x < pList.Count; y++, x++)
newList.Add(pList[x]);
dict.Add(dict.Count, newList);
}
return dict;
}
And then you can do this:
var groups = new[]
{
"Item1",
"Item2",
"Item3",
"Item4",
"Item5",
"Item6",
"Item7",
"Item8"
}.ToGroupedDictionary(3);
I need to create pairs / triples of something and store it somewhere. How can I do it?
I tried:
for (int i = 0; i < 100; i++)
{
var item=new { a=i , b="lala" ,c=4.5m}; //anonymous type
}
But then I thought: List<what>?
I could use dynamic but I want Intellisense.
(I could have also use Tuple<int,string,decimal> but if I already have what I need (=new { a=i , b="lala" ,c=4.5m};), why should I use other type (tuple)? )
Is there any solution to this?
You can use type inference
var items = Enumerable.Range(0,100)
.Select(i => new { a=i , b="lala", c=4.5m })
.ToList(); // not necessary (you can use IEnumerable)
Not sure, how you fill fields within for, but could you try:
var lstOfSmth = Enumerable.Range(0, 100)
.Select(i => new { a = i, b = "lala", c = 4.5m })
.ToList();
why should I use other type (tuple)
Because they have been designed exactly for this purpose. If you're afraid of verbose code, the using directive comes to the rescue, too.
using myPair = Tuple<int,string>;
using myTriple = Tuple<int,string,decimal>;
//...
for (int i = 0; i < 100; i++)
{
myPair pair = new myPair(1,"string");
myTriple triple = new myTriple(i,"lala", 4.5);
}