【问题标题】:C#, one-dimension wrapping arrayC#,一维包装数组
【发布时间】:2015-09-16 19:18:40
【问题描述】:

我有一个一维数组,我需要根据每个单元格的相邻单元格对其进行操作。

例如:

要在第一个单元格上运行操作,我需要访问最后一个单元格和第二个单元格。

第二个单元格,我需要访问第一个单元格和第三个单元格。

最后一个单元格,我需要访问第一个单元格和最后一个单元格之前的那个。

到目前为止我的代码是:

public static int[] firstRule(int[] numberArray)
{
    for (int i = 0; i < numberArray.Length; i++)
    {
        if (numberArray[numberArray.Length - 1 - i] == numberArray[i] + 1 
            && numberArray[i + 1] == numberArray[i] + 1)
        {
            numberArray[i] = numberArray[i] - 1;
        }
    }
    return numberArray;
}

但我的方法的问题在于它只适用于第一个单元格,因为它会正确地占用最后一个单元格和第二个单元格,但在那之后,一切都会崩溃。我不喜欢没有大量代码的帖子,但我不知道如何跟进。

我正在努力实现以下目标:

这些值是从 0 到 3 的数字。如果前面的单元格和后面的单元格都是相同的数字,我想将其更改为 x + 1
例如:假设我有 1 0 1 2 2。我想将 0 更改为 1。因为相邻单元格都是 0。

【问题讨论】:

  • 这些值是从0到3的数字。如果之前的单元格和之后的单元格都是相同的数字,我想将其更改为x + 1。
  • 例如:假设我有 1 0 1 2 2。我想将 0 更改为 1。因为相邻单元格都是 0。
  • 您能详细说明一下吗?我实际上认为这是解决问题的更好方法。
  • 您的例子在编写时没有意义,您正在寻找的术语是数组的“元素”。这闻起来像一个有问题的工作分配..
  • 你最终想要达到什么目标?...排序?

标签: c# arrays


【解决方案1】:

保持简单并使用变量来计算左右单元格索引。在你的 for 循环中,你可以这样做......

var leftCell = i - 1;
if (leftCell < 0)
{
    leftCell = numberArray.Length - 1; // Wrap around to the end...
}

var rightCell = i + 1;
if (rightCell > numberArray.Length - 1)
{
    rightCell = 0;  // Wrap back around to the beginning...
}


// Now you can update your original code to use these computed indices...
if (numberArray[leftCell] == numberArray[i] + 1 
    && numberArray[rightCell] == numberArray[i] + 1)
{
    numberArray[i] = numberArray[i] - 1;
}

【讨论】:

  • 也许我遗漏了一些东西,但是您不能简单地使用 mod 运算符来引用左、当前和右吗?即prev: (i-1) % arrayLength, current: i, next: (i+1)%arrayLength
  • @Tung (i-1 + arrayLength) % arrayLength 对于左索引更准确。试试 i=0
  • @Seven,真正的 C# 的 % 返回余数,而不是严格的“模”。
  • hmm.. 根据问题,numberArray[i] 的值在确定是否应该增加时根本不重要,(更不用说增加的值了)..numberArray[Leftcell] == numberArray[Rightcell] 应该是所有需要的,.. 但是我认为 OP 错误地忘记在他的问题中指定它.. 不过,我会更新这个答案以包括循环,声明变量之外的变量环形;做检查,分配与此分配,检查,(条件)分配。模式你要去这里。
【解决方案2】:

试试这个:

var len = numberArray.Length;
for (int i = 0; i < len; i++)
{
    var leftIndex = (i - 1 + len) % len;
    var rightIndex = (i + 1) % len;

    // do your stuff with numberArray[leftIndex] and numberArray[rightIndex] 
}

%mod operator% len 允许您停留在 0..len-1 范围内,因此您可以像遍历数组一样遍历数组,就好像它已变为“循环”

【讨论】:

  • ...在每次迭代中进行 2 次 mod 操作有什么意义?...避免每次迭代进行两次检查? i == 0 ? len - 1: i -1i == len ? 0 : i - 1
  • @BrettCaswell 只是为了保持简单和最易读。并非总是最快的解决方案就是最好的解决方案。
【解决方案3】:

来自您的 cmets。

这些值是从0到3的数字。如果之前的单元格和之后的单元格都是相同的数字,我想将其更改为x + 1
例如:假设我有 1 0 1 2 2。我想将 0 更改为 1。因为相邻单元格都是 0。

我会创建一个新数组,用现有数组的值填充它,然后根据现有数组中值的结果更改新数组的值。

在 Op 获取错误值时编辑 我怀疑您可能没有正确复制数组:

Existing Array array // The array you are passing in as parameter.

声明一个新的空数组:

int[] newArray;
int size = array.length;

for(int i =1; i<size-1;i++){

    if(array[i-1]==array[i+1])){
        newArray[i]=array[i]+1;
    }
    else{
        newArray[i]=array[i];
    }

}
if(array[size-1]==array[0]){
    newArray[size]= array[size]+1;
}
else{
        newArray[i]=array[i];
    }
if(array [size]==array[1]){
    newArray[0]= array[0]+1;
}
else{
        newArray[i]=array[i];
    }

如果数量有限制,并且在 2 之后恢复为零,那么只需对此进行简单的if 测试。

【讨论】:

  • 你是对的@Heyyou。但是我仍然在第三个 if 中使索引超出范围。而且我认为您在第二个 if 中忘记了 = 符号。
  • 由于相邻单元格都是 0。 没有相邻单元格都 0.. 这就是为什么它没有意义
  • 对,所以你通过省略无意义的部分来推断......这就是我的观点
  • 我正在努力让它工作。我会用我目前得到的内容更新我原来的帖子。
  • @FilipeTeles,如果你不能让它工作,为什么要把它标记为解决方案?
【解决方案4】:
int[] arr = new int[] { 1, 2, 3, 4, 5 };

var triples = arr.Select((n, i) =>
{
    if (i == 0)
        return Tuple.Create(arr[arr.Length - 1], arr[0], arr[1]);
    else if (i == arr.Length - 1)
        return Tuple.Create(arr[i - 1], arr[i], arr[0]);
    else
        return Tuple.Create(arr[i - 1], arr[i], arr[i + 1]);
});

foreach (var triple in triples)
{
    Console.WriteLine(triple.Item1 + " " + triple.Item2 + " " + triple.Item3);
}

【讨论】:

    【解决方案5】:
    public static void firstRule(int[] numberArray)
    {
        for (int i = 0; i < numberArray.Length; i++)
        {
            int? prevElement = i == 0 
                ? numberArray[numberArray.Length-1]
                : numberArray[i - 1];
    
            int? nextElement = i == numberArray.Length -1
                ? numberArray[0]
                : numberArray[i + 1];
    
            Console.WriteLine(
                String.Format("Prev: {0}; Current: {1}; Next: {2}",
                    prevElement,
                    numberArray[i],
                    nextElement)
                );
        }
    }
    

    然后调用firstRule(new int[]{ 1, 2, 3 }); 打印:

    Prev: 3; Current: 1; Next: 2
    Prev: 1; Current: 2; Next: 3
    Prev: 2; Current: 3; Next: 1
    

    【讨论】:

    • 这不是环绕,因此 i = 0 的前一个元素是 3,而不是 null
    【解决方案6】:

    选项 1

    不管分配

        public static int[] firstRule(int[] numberArray)
        {
            int left,right;
            for (int i = 0, max = numberArray.Length - 1; i <= max; i++)
            {                
                left = (i == 0) ? max : i - 1; 
                right = (i == max) ? 0 : i + 1;
    
                numberArray[i] = (numberArray[left] == numberArray[right]) ? numberArray[i] + 1 : numberArray[i]; //always peforms an assignment;
            }
            return numberArray;
        }
    

    选项 2

    有条件地赋值

        public static int[] secondRule(int[] numberArray)
        {
            int left,right;
            for (int i = 0, max = numberArray.Length - 1; i <= max; i++)
            {   
                left = (i == 0) ? max : i - 1; 
                right = (i == max) ? 0 : i + 1;
    
                if (numberArray[left] == numberArray[right])
                {
                   numberArray[i]++;
                }
            }
            return numberArray;
        }
    

    选项 3

    left 和 right 在每次迭代中只使用 1 次.. 那么为什么还要将它们分配给一个变量呢???...

        public static int[] thirdRule(int[] numberArray)
        {            
            for (int i = 0, max = numberArray.Length - 1; i <= max; i++)
            {                
                if (numberArray[(i == 0) ? max : i - 1] == numberArray[(i == max) ? 0 : i + 1])
                {
                    numberArray[i]++; // what happens if numberArray[i] is 3, should it become 4 or 0?
                }
            }
            return numberArray;
        }
    

    选项 4(不安全)

    不安全 - 固定 - 指针

        public static int[] fourthRule(int[] numberArray)
        {
            unsafe {
                int* pointer, right, left; 
    
                for (int i = 0, max = numberArray.Length - 1; i <= max; i++)
                {
                    fixed (int* p1 = &numberArray[0], p2 = &numberArray[i], p3 = &numberArray[max])
                    {
                        pointer = p2;
                        if (i == 0)
                        {
                            left = p3;
                            right = pointer;
                            right++;
                        }
                        else if (i == max)
                        {
                            left = pointer;
                            left--;
                            right = p1;
                        } 
                        else
                        {
                            left = pointer;
                            left--;
                            right = pointer;
                            right++;
                        }
    
                        if (*right == *left) {
                            *pointer = *pointer + 1;
                        }
                    }
                }
            }
            return numberArray;
        }  
    

    【讨论】:

    • 这假设您的 int[] 长度大于 2
    【解决方案7】:

    最近自己遇到了这个问题,发现这是一个可靠的方法。 `

    int length = numberArray.Length; 
    for (int i = 0; i < length; ++i)
    {
        int iMinus = (((i - 1) % length) + length) % length;
        int iPlus = (((i + 1) % length) + length) % length;
    }`
    

    【讨论】:

      【解决方案8】:

      这样的事情应该可以工作。它为每个循环中的操作确定适当的单元格并执行操作。您没有说明该操作是什么,因此您需要填写 DoYourOperation 方法。

      public static int[] processArray(int[] numberArray)
      {
          for (int i= 0; i < numberArray.Length; i++)
          {
              int firstCell;
              int secondCell;
              //Check if first cell
              if(i == 0)
              { 
                  firstCell = numberArray[numberArray.length-1]; //Last cell
                  secondCell = numberArray[i++]; //Next cell
              } 
              //Check if last cell
              else if(i == numberArray.Length - 1)
              { 
                  firstCell = numberArray[i--]; //Cell before last one
                  secondCell = numberArray[0]; //First cell
              }  
              else
              {
                  firstCell = numberArray[i--];
                  secondCell = numberArray[i++];
              }
      
              DoYourOperation(firstCell, secondCell);
          }  
      }
      

      【讨论】:

      • 您需要将循环中的所有i++i-- 调用替换为i + 1i - 1,因为这将更新i 的值,而您甚至不会得到返回的正确值(它返回 i 然后递增或递减)。
      • 是的,虽然在阅读了关于这个问题的 cmets 之后,我似乎误解了这个问题。
      猜你喜欢
      • 2014-05-27
      • 1970-01-01
      • 2021-03-07
      • 1970-01-01
      • 2013-11-23
      • 1970-01-01
      • 2011-03-27
      • 2019-01-15
      • 2021-11-23
      相关资源
      最近更新 更多