I'd like help* in creating a method or (linq) expression that can row-wise concatenate lists (of varying lengths) of jagged arrays as the one below:
List<double[][]> orgArrayList = new List<double[][]>();
double[][] one = {
new [] {5d, 6},
new [] {7d, 9}};
double [][] two = {
new [] {5d, 6},
new [] {7d, 9}};
double [][] three= {
new [] {5d, 6},
new [] {7d, 9}};
orgArrayList.AddRange(new[] {one, two, three});
So that the resulting array will be equal to this one:
double[][] expected = {
new [] {5d, 6, 5, 6, 5, 6},
new [] {7d, 9, 7, 9, 7, 9}};
The number of jagged arrays in my input list(s) will be >=1. All arrays within a single list will be jagged with 2 dimensions, but none of the 2 dimensions will have a fixed/known length (size).
*'help' being a euphemism for someone telling me how to do it
You could start with something like this, which appends the elements of each row of add[] to the rows of src[], producing a new 2-dimensional array:
public static double[][] AppendToRows(double[][] src, double[][] add)
{
// Allocate new array to hold elements from src[] and add[]
double[][] res = new double[src.Length][];
// Append elements to each row of res[]
for (int i = 0; i < src.Length; i++)
{
// Allocate row res[i] large enough to hold elements from src[i] and add[i]
res[i] = new double[src[i].Length + add[i].Length];
// Copy/append elements from src[i] to res[i]
int ri = 0;
for (int j = 0; j < src[i].Length; j++)
res[i][ri++] = src[i][j];
// Copy/append elements from add[i] to res[i]
if (i >= add.Length)
continue;
for (int j = 0; j < add[i].Length; j++)
res[i][ri++] = add[i][j];
}
return res;
}
To append multiple arrays together, just call this method multiple times, once for each additional array that needs to be concatenated onto the resulting array.
A more comprehensive solution would be to take a List<double[][]> of input arrays, and to loop through each array in the list as you build each row of the result. But I have left that as an exercise for the reader.
You can create an extension, that will concatenate arrays the way you need, so it will looks like Linq:
public static class Extension
{
public static T[][] ConcatArrays<T>(this T[][] array, T[][] concatWith)
{
var max = Math.Max(array.Length, concatWith.Length);
var result = new T[max][];
for (var index = 0; index < max; index++)
{
var list = new List<T>();
if (index < array.Length)
{
list.AddRange(array[index]);
}
if (index < concatWith.Length)
{
list.AddRange(concatWith[index]);
}
result[index] = list.ToArray();
}
return result;
}
}
So the usage of this is:
var expected = one.ConcatArrays(two).ConcatArrays(three);
Hope it makes sense
As a final solution for my use case I simply combined David's and Valdimir's answer into a single method that can handle lists of varying lengths (>=1).
// ========================================
// My interpretation of David's suggestion
// using Valdimir's solution as a basis
// ========================================
public static double[][] RowWiseConcatListedJaggedArrays(List<double[][]> listOfJaggedArray)
{
var resArray = listOfJaggedArray[0];
for (int rInd = 1; rInd < listOfJaggedArray.Count; rInd++)
{
resArray = resArray.ConcatArrays(listOfJaggedArray[rInd]);
}
return resArray;
}
And putting everything together...
using System;
using System.Collections.Generic;
namespace RowWiseConcat
{
public static class Extension
{
// ====================
// Vladimir's solution
// ====================
public static T[][] ConcatArrays<T>(this T[][] array, T[][] concatWith)
{
var max = Math.Max(array.Length, concatWith.Length);
var result = new T[max][];
for (var index = 0; index < max; index++)
{
var list = new List<T>();
if (index < array.Length)
{
list.AddRange(array[index]);
}
if (index < concatWith.Length)
{
list.AddRange(concatWith[index]);
}
result[index] = list.ToArray();
}
return result;
}
}
class Program
{
// ========================================
// My interpretation of David's suggestion
// using Valdimir's solution as a basis
// ========================================
public static double[][] RowWiseConcatListedJaggedArrays(List<double[][]> listOfJaggedArray)
{
var resArray = listOfJaggedArray[0];
for (int rInd = 1; rInd < listOfJaggedArray.Count; rInd++)
{
resArray = resArray.ConcatArrays(listOfJaggedArray[rInd]);
}
return resArray;
}
static void Main(string[] args)
{
// ... do something that results in orgArrayList, e.g.
double[][] one =
{
new[] {5d, 6},
new[] {7d, 9}
};
double[][] two =
{
new[] {5d, 6},
new[] {7d, 9}
};
double[][] three =
{
new[] {5d, 6},
new[] {7d, 9}
};
List<double[][]> orgArrayList = new List<double[][]>()
{ one, two, three};
// Concat list items
var resArray = RowWiseConcatListedJaggedArrays(orgArrayList);
// ... continue with resArray
}
}
}
Related
I have a 2D string array.
I just want to randomize the rows order and shuffle the items within each row.
So for example:
[1,2
3,4]
I want it to be as below, row pairs stay same here (order change is valid):
[4,3
1,2] or
[3,4
2,1] or
[4,3
2,1] or
[1,2
3,4] or
[2,1
3,4] or
[2,1
4,3] or
[3,4
1,2]
and i want to avoid below shuffling because i'll read my array row by row, i want to keep my rows to contain same elements. I want to keep my row pairs. Below, my [1,2] and [3,4] rows does not exist anymore :
[1,3
2,4] or
[3,1
4,2] or
[3,1
2,4] or
[1,4
2,3] ....
So here is my array:
array_to_shuffle = new string[len_2d,2];
Shuffle(array_to_shuffle);
and the function i need help :
public void Shuffle(Random rand, string[,] array)
{
rand = new Random();
int[] randomised_array = new int[len_2d];
for (int i = 0; i < len_2d; i++)
{
randomised_array[i] = i;
}
int[] MyRandomArray = randomised_array.OrderBy(x => rand.Next()).ToArray();
string tmp1 = String.Empty;
string tmp2 = String.Empty;
array[MyRandomArray[0], 0] = tmp1;
array[MyRandomArray[0], 1] = tmp2;
array[MyRandomArray[0], 0] = array[MyRandomArray[1],0];
array[MyRandomArray[0], 1] = array[MyRandomArray[1],1];
array[MyRandomArray[1], 0] = tmp2;
array[MyRandomArray[1], 1] = tmp1;
}
Thank you everyone...
Try this code (necessary comments are in code):
static void Main(string[] args)
{
int[,] matrix = { { 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 }, { 9, 10 }, { 11, 12 } };
matrix = Shuffle(matrix);
}
static T[,] Shuffle<T>(T[,] matrix)
{
int howManyRows = matrix.GetLength(0);
int howManyColumns = matrix.GetLength(1);
T[,] randomizedMatrix = new T[howManyRows, howManyColumns];
//we will use those arrays to randomize indexes
int[] shuffledRowIndexes = Enumerable.Range(0, howManyRows).ToArray();
int[] shuffledColumnIndexes = Enumerable.Range(0, howManyColumns).ToArray();
Random rnd = new Random();
shuffledRowIndexes = shuffledRowIndexes.OrderBy(x => rnd.Next()).ToArray();
for (int i = 0; i < howManyRows; i++)
{
// at every loop we get new randomized column idexes, so every row will be shuffled independently
shuffledColumnIndexes = shuffledColumnIndexes.OrderBy(x => rnd.Next()).ToArray();
for (int j = 0; j < howManyColumns; j++)
randomizedMatrix[i, j] = matrix[shuffledRowIndexes.ElementAt(i), shuffledColumnIndexes.ElementAt(j)];
}
return randomizedMatrix;
}
Helpful articles:
Best way to randomize an array with .NET
What are the differences between a multidimensional array and an array of arrays in C#?
If there are multiple string with same length(max), how do I find out all the indices. I am getting the first index currently. Is there a better way to do this?
using System;
using System.Linq;
namespace Examples
{
class Program
{
static void Main(string[] args)
{
Longestword("Find the largest word with lower index abcdefg ");
Console.ReadKey();
}
private static void Longestword(String sen)
{
String[] sArray = sen.Split(null);
int[] cArr = new int[sArray.Length];
for (int i = 0; i < sArray.Length; i++)
{
int j = sArray[i].Length;
cArr[i] = j;
}
int max = cArr.Max();
int index = cArr.ToList().IndexOf(max);
Console.WriteLine(index);
}
}
}
Here's my stab at a solution:
public static class LinqExtensions
{
public static List<int> IndicesOf(this int[] array, int item)
{
var indices = new List<int>();
for (int i = 0; i < array.Length; i++)
{
if (array[i] == item)
indices.Add(i);
}
return indices;
}
}
You can then call it like this:
int[] someArrayFindMax = new[] { 1, 4, 45, 23, 4, 3342, 34, 3342, 4, 3342, 3342 };
int max = someArrayFindMax.Max();
List<int> indices = someArrayFindMax.IndicesOf(max);
Here's another possible extension method for finding the indices of the longest strings directly:
public static List<int> LongestStringIndices(this string[] strings)
{
int longestString = -1;
var indices = new List<int>();
for (int i = 0; i < strings.Length; i++)
{
if (strings[i].Length > longestString)
{
longestString = strings[i].Length;
// We're no longer interested in the indices of the
// strings we now know to be shorter
indices.Clear();
indices.Add(i);
}
else if (strings[i].Length == longestString)
{
indices.Add(i);
}
// If it's less than the max length so far we ignore it
}
return indices;
}
I'd play with LINQ, as it's the C#-ish way.
Here's a fiddle: https://dotnetfiddle.net/NEFkqb
List<string> words = new List<string>{"aaaa","bb","cccc"};
List<int> lengths = words.Select(word => word.Length).ToList();
int max = lengths.Max();
List<int> maxes = new List<int>();
for(int i = 0; i < lengths.Count; i++)
if(lengths[i] == max)
maxes.Add(i);
My array is below
int[] T1 = new int[]{1,5,4};
int[] T2 = new int[]{2,4,3};
int[] T3 = new int[]{7,9,1};
A result of the sequence I want it is as follows .
int[] result = {7,9,4}
I want to look for a max value same index[(e.g) 1,2,7) in array.
and Merging array is int[] result = {7,9,4}
please let me know best way
thanks
Here is a simple method for performing your desired operation.
int[] result = new int[T1.Length];
for (int i = 0; i < T1.Length; i++)
{
result[i] = new[] {T1[i], T2[i], T3[i]}.Max();
}
You'll have to add using System.Linq in order to enable the Max() extension.
EDIT
Here is a method that allows you to use any number of arrays:
static T[] MaxElements<T>(params T[][] arrays) where T : IComparable<T>
{
return Enumerable.Range(0, arrays[0].Length)
.Select(i => Enumerable.Range(0, arrays.Length)
.Select(a => arrays[a][i]).Max()).ToArray();
}
You'll have to add the using System.Linq; for this one too. You'll have to make sure that all the elements passed in have the same lengths else you will run into an IndexOutOfRangeException.
It can be used as follows;
var result = MaxElements(T1, T2, T3);
Here is what you need:
static void Main(string[] args)
{
GetMaxArray(new[] { 1, 5, 4 }, new[] { 2, 4, 3 }, new[] { 7, 9, 1 });
}
private static void GetMaxArray(params int[][] m)
{
var length = m.First().Length;
var r = new int[length];
for (var i = 0; i < length; i++)
r[i] = m.Select(a => a[i]).Max();
}
public int[] GetMaxValueArray(List<int[]> arrayList)
{
int[] result = null;
int maxArraySize;
int maxCurrentArrayItemValue;
if (arrayList != null && arrayList.Count > 0)
{
maxArraySize = 0;
foreach (int[] array in arrayList)
if (array.Length > maxArraySize)
maxArraySize = array.Length;
result = new int[maxArraySize];
for (int i = 0; i < maxArraySize; i++)
{
maxCurrentArrayItemValue = 0;
foreach (int[] array in arrayList)
if (i < array.Length)
if (array[i] > maxCurrentArrayItemValue)
maxCurrentArrayItemValue = array[i];
result[i] = maxCurrentArrayItemValue;
}
}
return result;
}
Can't figure out why the line winningNumbers[i] += count; comes up as outside the bounds of the array.
static int[] CheckWinningNumbers(int[][]lottoNumbers, int[]drawNumbers)
{
int[] winningNumbers = new int[8];
for (int i = 0; i < lottoNumbers.Length; i++)
{
int k = 0;
int count = 0;
for (int j = 0; j < lottoNumbers[i].Length; j++)
{
if (lottoNumbers[i][j] == drawNumbers[k])
{
count +=1;
}
k += 1;
winningNumbers[i] += count;
}
}
return winningNumbers;
Just replace
int[] winningNumbers = new int[8];
With
int[] winningNumbers = new int[lottoNumbers.Length];
As long as you are iterating lottoNumbers.Length the variable i will not exceed its boundaries.
Edit
I ran it with the following data and it works
int[][] lottoNumbers = { new[] { 1, 2 },
new[]{ 3, 4 },
new[]{ 5, 6 },
new[]{ 7, 8 } };
int[] drawNumbers = {1, 4, 5, 8};
I don't know what data you are testing it on but you are using jagged arrays intead of multidimensional. this will not guarantee that all your sub arrays have the same length which might be problematic. If all the arrays have the same length and performance is not critical here I'd suggest you use Multidimensional Arrays
to convert a list to array[,] there is code:
double[,] arr = new double[list.Count, list[0].Length];
for (int i = 0; i < list.Count; i++)
{
for (int j = 0; j < list[0].Length; j++)
{
arr[i, j] = list[i][j];
}
}
I want to convert it to flatten array so Using the fact
Flattened array index computation
array[(Y coordinate * width) + X coordinate]
2D array index computation
array[Y coordinate, X coordinate]
code changes to
double[] arr = new double[list.Count * list[0].Length];
for (int i = 0; i < list.Count ; i++)
{
for (int j = 0; j < list[0].Length; j++)
{
arr[i] = list[i * list[0].Length + j];
}
}
But What would be the code to convert a List < List < double > > to flatten array?
Is it possible to do it in 2 loops as the above code?
the List<List<double>> represents a double[,] arr
Honestly I'm not 100% sure what you're asking, but to flatten a List<List<>> you can use SelectMany from Linq, here's a simple example:
static void Main(string[] args)
{
var first = new List<double> {1, 2, 3};
var second = new List<double> { 3, 4, 5 };
var lists = new List<List<double>> {first, second};
var flatten = lists.SelectMany(a => a).ToArray();
foreach (var i in flatten)
{
Console.WriteLine(i);
}
}
Given the fact that your list ist a nested enumerable you can simply use Linq.
double[] array = nestedList.SelectMany(a => a).ToArray();
In a loop (i.e. without LINQ) would be something like
public static void Main()
{
List<List<double>> listOfLists = new List<List<double>>();
listOfLists.Add(new List<double>() { 1, 2, 3 });
listOfLists.Add(new List<double>() { 4, 6 });
int flatLength = 0;
foreach (List<double> list in listOfLists)
flatLength += list.Count;
double[] flattened = new double[flatLength];
int iFlat = 0;
foreach (List<double> list in listOfLists)
foreach (double d in list)
flattened[iFlat++] = d;
foreach (double d in flattened)
Console.Write("{0} ", d);
Console.ReadLine();
}