Convert a DataTable to multidimensional array C# - c#

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");
}

Related

Sorting array by frequency of elements in C#

Here is what i have so far
int[] numbers = { 3,5,4,3,8,8,5,3,2,1,9,5 };
int[] n = new int[12];
int[] k;
foreach (int number in numbers)
{
n[number]++;
}
Array.Sort(n);
Array.Reverse(n);
foreach (int value in n)
{
Console.WriteLine(value);
}
I know i am missing the part where i sort the frequency of the elements after i counted them and i just cant get my head around it. I'd appreciate some help, Thanks!
What's the problem with your solution ?
Whereas you correctly keep the frequencies of the numbers in the table called n in your code, which hereby I would call it frequencies, then you Sort this array. This action breaks your solution, since each frequency is associated with the corresponding index of its location in the array.
E.g. If an instance of this array is this [8,2,1,7,6]. When you call the Sort method on this array, this would have as a result the array to be sorted and the order of the elements of the array would be this [1,2,7,6,8]. Before calling sort, the first element of the array was indicating that the number 0 (the index of the first element is 0) has been found 8 times in our numbers. After sort, the first element is 1, which means now that the frequency of the number 0 is 1, which is apparently wrong.
If you want to keep it your way, then you could try something like this:
int[] numbers = { 1,2,2,9,1,2,5,5,5,5,2 };
int[] frequencies = new int[12];
int k = 3;
foreach (int number in numbers)
{
frequencies[number]++;
}
var mostFrequentNumbers = frequencies.Select((frequency, index) => new
{
Number = index,
Frequency = frequency
})
.OrderByDescending(item => item.Frequency)
.Select(item => item.Number)
.Take(k);
foreach (int mostFrequentNumber in mostFrequentNumbers)
{
Console.WriteLine(mostFrequentNumber);
}
Are there any other approaches ?
An easy way to do this is to use a data structure like a Dictionary, in which you would keep as keys the numbers and as the corresponding values the corresponding frequencies.
Then you can order by descending values the above data structure an keep the k most frequent numbers.
int[] numbers = { 1,2,2,9,1,2,5,5,5,5,2 };
int k = 3;
Dictionary<int, int> numberFrequencies = new Dictionary<int, int>();
foreach (int number in numbers)
{
if(numberFrequencies.ContainsKey(number))
{
numberFrequencies[number] += 1;
}
else
{
numberFrequencies.Add(number, 1);
}
}
var mostFrequentNumbers = numberFrequencies.OrderByDescending(numberFrequency => numberFrequency.Value)
.Take(k)
.Select(numberFrequency => numberFrequency.Key);
foreach (int mostFrequentNumber in mostFrequentNumbers)
{
Console.WriteLine(mostFrequentNumber);
}
You can also achieve the same thing by only using LINQ:
int[] numbers = { 1,2,2,9,1,2,5,5,5,5,2 };
int k = 3;
var mostFrequentNumbers = numbers.GroupBy(number => number)
.ToDictionary(gr => gr.Key, gr => gr.Count())
.OrderByDescending(keyValue => keyValue.Value)
.Take(k)
.Select(numberFrequency => numberFrequency.Key);
foreach (int mostFrequentNumber in mostFrequentNumbers)
{
Console.WriteLine(mostFrequentNumber);
}
You can just use Linq extensions:
using System.Linq;
using System.Collections.Generic;
...
private static IEnumerable<int> Solve(int[] numbers, int k) {
return numbers
.GroupBy(x => x)
.OrderByDescending(g => g.Count())
.Select(g => g.Key)
.Take(k);
}
Then you can call:
var numbers = new []{1,2,2,9,1,2,5,5,5,5,2};
var k = 3;
var result = Solve(numbers, k);
foreach (int n in result)
Console.WriteLine(n);
To be very terse:
var frequents = numbers.GroupBy(t => t)
.Where(grp => grp.Count() > 1)
.Select(t => t.Key)
.OrderByDescending(t => t)
.Take(k)
.ToList();

c# - LINQ find 2D jagged array minimum, return index

I have a standard 2D jagged array int[][] arr.
Let's call i and j the indices for row and column.
I'd like to retrieve via LINQ the indices i and j which points to the minimum of the matrix.
An idea of what I am trying to achieve is bri
from num in arr
where min = (from num in arr select min(num))
select i, j
You can also do this:
var result = from i in Enumerable.Range(0, arr.Length)
from j in Enumerable.Range(0, arr[i].Length)
orderby arr[i][j]
select new { i, j };
var r = result.FirstOrDefault();// here is the indexes of min value
You can use the the overloads of SelectMany and Select that include the index and then OrderBy and First to get one of the sets of indexes with the minimum value.
var min = arr.SelectMany((subArr, i) => subArr.Select((value, j) => new { i, j, value }))
.OrderBy(x => x.value)
.First();
int firstIndex = min.i;
int secondIndex = min.j;

Fetch (x,y) from a 2D Array where condition matches

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.

Datatable to array and then to a Textbox

I have a datatable with only one column and rows with just some integers. I would like to transition them into a array so I can display them in a textbox
You can use Linq and String.Join:
int[] nums = table.AsEnumerable().Select(r => r.Field<int>(0)).ToArray();
TextBoxNums.Text = string.Join(",", nums);
If you want to split them by a new line:
string[] nums = table.AsEnumerable().Select(r => r.Field<int>(0).ToString()).ToArray();
TextBoxNums.Lines = nums;

Convert List<double[]> to double[,]

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?

Categories

Resources