Как преобразовать int[] в int [,] - C#
у меня есть массив int в одном измерении:
var intArray=new[] { 1, 2, 3, 4, 5, 6 };
и я хочу преобразовать его в два измерения, такие как:
var intArray2D=new[,] { {1, 2}, {3, 4}, {5, 6} };
как этого добиться с помощью C#?
8 ответов
Я считаю, что вы хотите разделить целочисленный массив на массив из двух целых чисел каждый:
int[] list = new int[] { 1, 2, 3, 4, 5, 6};
int[][] newlist = new int[list.Length / 2][];
for (int i = 0, n = 0; i < list.Length; i += 2, n++)
{
newlist[n] = new[] { list[i], list[i + 1] };
}
присвоить Points
в частности, вы могли бы попробовать:
List<Point> plist = new List<Point>();
for (int i = 0; i < list.Length; i += 2)
{
plist.Add(new Point(list[i], list[i + 1]));
}
С петлей возможно:
for (int i = 0; i < oldArr.Length; i=i+2)
{
newArr[i/2, 0] = oldArr[i];
newArr[i/2, 1] = oldArr[i + 1];
}
непроверенный, но вы должны указать в правильном направлении...
если одномерный массив содержит примитивные данные в строка основного порядка, и общая емкость 2-мерного массива равна длине одномерного массива, вы можете использовать это.
int[] source = new int[6];
int[,] target = new int[3, 2];
Buffer.BlockCopy(source, 0, target, 0, source.Length * sizeof(int));
обратите внимание, что в отличие от Array.Copy
и другие методы массива/списка,Buffer.BlockCopy
работает на ряде байт данных, даже если каждый элемент массива больше, чем 1 байт. Он также работает только с массивами примитивных данных типы.
Дополнительные ссылки:
- многомерные массивы хранятся в порядке строк (ECMA-335 раздел I, §8.9.1)
Buffer.BlockCopy
Edit: вот полный модульный тест.
[TestMethod]
public void SOTest16203210()
{
int[] source = new int[6] { 1, 2, 3, 4, 5, 6 };
int[,] destination = new int[3, 2];
Buffer.BlockCopy(source, 0, destination, 0, source.Length * sizeof(int));
Assert.AreEqual(destination[0, 0], 1);
Assert.AreEqual(destination[0, 1], 2);
Assert.AreEqual(destination[1, 0], 3);
Assert.AreEqual(destination[1, 1], 4);
Assert.AreEqual(destination[2, 0], 5);
Assert.AreEqual(destination[2, 1], 6);
}
вы можете использовать этот код. здесь вы можете отправить любую длину вы хотите. вы можете "deivde" Арри[] к Арри [,] для любой lenth.2 или 3 или что угодно! пока размер % a.длина = = 0 !!!!
код
static int[,] convert(int[] a, int size)
{
int[,] value = new int[a.Length / size, size];
int counter = 0;
//
for (int b = 0; b < value.GetLength(0); b++)
for (int c = 0; c < value.GetLength(1); c++)
{
value[b, c] = a[counter];
counter++;
}
return value;
}
Если произведение измерений одинаковое, самым быстрым способом, вероятно, было бы закрепить матрицу с помощью фиксированного оператора, а затем использовать класс маршалинга для копирования непрерывного блока из массива в IntPtr, созданный из void*, который вы получили от фиксированного.
вам придется обернуть это в небезопасный оператор и включить небезопасный в конфигурации сборки сборки.
я преобразовал это из vb в c#
int Size = OldArray.Length;
int[,] NewPoints = null;
if (Size % 2 != 0) {
//Error - Array has odd number of elements!
} else {
for (i = 0; i <= Size - 1; i += 2) {
Array.Resize(ref AllPoints, (i / 2) + 1, 2);
NewPoints[i / 2, 0] = OldArray(i);
NewPoints[i / 2, 1] = OldArray(i + 1);
}
}
вы можете попробовать это:
int [] a = {1,2,3,4,5,6};
int [,] b = new int[a.Length/2,2];
for(int i = 0;i<a.Length;i++)
{
b[i/2,i%2] = a[i];
}
обратите внимание, что i / 2 является целочисленным делением, поэтому как 4/2, так и 5/2 дадут 2, который является правильным индексом в 2Darray для кортежа 5 и 6 из исходного массива. Второй индекс определяется с помощью напоминания при делении на 2, он даст 0, если индекс четное число и 1, если индекс элемента из исходного массива нечетное число.
Я бы рассмотрел это для любого измерения массива:
public class TestClass {
public static void TestMethod2D() {
var intLinear=new[] { 1, 2, 3, 4, 5, 6 };
var indexer2D=new ArrayIndexer<int>(3, 2);
for(var i=intLinear.Length; i-->0; indexer2D[i]=intLinear[i])
;
var int2D=(int[,])indexer2D.ToArray();
}
public static void TestMethod4D() {
var intLinear=new[] { 1, 2, 3, 4, 5, 6 };
var indexer4D=new ArrayIndexer<int>(2, 2, 2, 2);
for(var i=intLinear.Length; i-->0; indexer4D[i]=intLinear[i])
;
var int4D=(int[, , ,])indexer4D.ToArray();
}
}
public partial class ArrayIndexer<T> {
public Array ToArray() {
return m_Array;
}
public ArrayIndexer(params int[] lengths) {
m_Array=Array.CreateInstance(typeof(T), lengths);
}
public T this[params int[] indices] {
set {
m_Array.SetValue(value, indices.Transform(m_Array));
}
get {
return (T)m_Array.GetValue(indices.Transform(m_Array));
}
}
Array m_Array;
}
public static partial class ArrayExtensions {
public static int[] Transform(
this int[] indices, Array array, bool isRowMajor=true) {
if(indices.Length>array.Rank)
return indices;
else {
var list=indices.ToList();
if(isRowMajor)
list.Reverse();
for(int r, q=0, i=0, count=array.Rank; count-->0; ++i) {
var index=isRowMajor?count-i:i;
if(indices.Length>i) {
q=Math.DivRem(indices[i]+q, array.GetLength(index), out r);
list[i]=r;
}
else {
if(index<0) {
list.Add(q);
q=0;
}
else {
q=Math.DivRem(q, array.GetLength(index), out r);
list.Add(r);
}
}
}
if(isRowMajor)
list.Reverse();
return list.ToArray();
}
}
}
ArrayExtensions.Transform
является преобразователем индексов, он выполняет линейное преобразование с геометрией заданного массива. isRowMajor
управляет макетом, например, вы считаете int[,]
на x, y
или y, x
порядок.