如何交换数组中两个不同长度的变量组?

问题描述 投票:0回答:3

如何在同一个数组中交换同一个数组的两个不同长度的变量组?即使我需要 C# 中的代码,同时理论过程对我来说就足够了。

我已经尝试了几种方法,但我一直在寻找一种不那么多余和/或不那么重的方法。

例如我有

string[] lines
这些行:

line 0
line 1
line 2
line 3
line 4
line 5
line 6
line 7
line 8

如果你想用第 5 6 行交换第 1 2 3 行,这应该是这样的:

line 0
line 5
line 6
line 4
line 1
line 2
line 3
line 7
line 8

n.b. : 每次要交换的行和行数都是不同的。

我把我的代码放在这里:交换数组中两个不同长度的变量组.

c# arrays visual-studio-2022 swap
3个回答
0
投票
public static class Extension
{
    public static string[] Shift(this string[] array, int startIndex, int length, int newIndex)
    {
        string[] items = array.Skip(startIndex).Take(length).ToArray();
        ArrayList arrayList = new ArrayList(array);
        arrayList.RemoveRange(startIndex, length);
        arrayList.InsertRange(newIndex, items);

        arrayList.CopyTo(array);
        return array;
    }
}

private static void Main(string[] args)
{
    string[] array =
        {
        "line 0",
        "line 1",
        "line 2",
        "line 3",
        "line 4",
        "line 5",
        "line 6",
        "line 7",
        "line 8"
    };
    array = array.Shift(5, 2, 1);
    array = array.Shift(3, 3, 4);
}

可以用扩展类来做。没有经过全面测试。


0
投票

有结果

0,1,2,3,4,5,6,7,8,9,10
0,8,9,5,6,7,1,2,3,4,10

我有以下代码:

internal class Program
{
    static void Main(string[] args)
    {
        int[] array = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

        Console.WriteLine(string.Join(",", array));

        SwapElements(ref array, 1..5, 8..10);

        Console.WriteLine(string.Join(",", array));
    }

    static void SwapElements<T>(ref T[] array, Range a, Range b)
    {
        (int a_Offset, int a_Length) = a.GetOffsetAndLength(array.Length);
        (int b_Offset, int b_Length) = b.GetOffsetAndLength(array.Length);

        if (a_Offset > b_Offset)
        {
            ((b_Offset, b_Length), (a_Offset, a_Length)) = ((a_Offset, a_Length), (b_Offset, b_Length));
        }

        Range pre_a = Range.EndAt(a_Offset);
        a = new Range(a_Offset, a_Offset + a_Length);
        Range between = new Range(a_Offset + a_Length, b_Offset);
        b = new Range(b_Offset, b_Offset + b_Length);
        Range post_b = Range.StartAt(b_Offset + b_Length);

        array = Concat(array[pre_a], array[b], array[between], array[a], array[post_b]);
    }

    /// <summary>
    /// Concatenates two or more arrays into a single one.
    /// </summary>
    /// <remarks>
    /// Code taken from https://stackoverflow.com/a/52749536/380384
    /// </remarks>
    public static T[] Concat<T>(params T[][] arrays)
    {
        // return (from array in arrays from arr in array select arr).ToArray();

        var result = new T[arrays.Sum(a => a.Length)];
        int offset = 0;
        for (int x = 0; x < arrays.Length; x++)
        {
            arrays[x].CopyTo(result, offset);
            offset += arrays[x].Length;
        }
        return result;
    }
}

笔记。

  1. 我正在使用

    Range
    对象来定义要交换的数组切片。我使用从 [SO] 窃取的自定义
    Concat
    函数从不同的切片重新组装数组。在操作之前对切片进行排序,以确保正确定义两个切片之间的元素。

  2. C# 范围出于某种原因使用一些晦涩的概念将

    start
    end
    的范围定义为
    start..(end+1)
    。 70 年前,Fortran 对
    start:end
    做了同样的事情,这是有道理的,此后的所有其他矢量语言(如 Matlab 等),但是当 C# 引入切片时,他们完全 foobar'd 以使其无缘无故地像 Python .吐槽完毕


0
投票
public static T[] Swap<T>(this T[] array, int startIndexA, int lengthA, int startIndexB, int lengthB) 
{
    List<T[]> arrays = new List<T[]>();

    if(startIndexA > startIndexB)
    {
        int tempIndex = startIndexA;
        int tempLength = lengthA;

        startIndexA = startIndexB;
        lengthA = lengthB;

        startIndexB = tempIndex;
        lengthB = tempLength;
    }

    var sliceA = array[startIndexA..(startIndexA + lengthA)];
    var sliceB = array[startIndexB..(startIndexB + lengthB)];


    if (startIndexA > 0)
        arrays.Add(array[0..startIndexA]);

    arrays.Add(sliceB);

    if (startIndexA + sliceA.Length < startIndexB)
        arrays.Add(array[(startIndexA + sliceA.Length)..startIndexB]);

    arrays.Add(sliceA);

    if ((startIndexB + sliceB.Length) < array.Length)
        arrays.Add(array[(startIndexB + sliceB.Length)..]);

    return arrays.SelectMany(a => a).ToArray();
}

按如下方式调用

string[] array =
            {
            "line 0",
            "line 1",
            "line 2",
            "line 3",
            "line 4",
            "line 5",
            "line 6",
            "line 7",
            "line 8"
        };
    var result = array.Swap(5, 2, 1, 3);
© www.soinside.com 2019 - 2024. All rights reserved.