如何在数组中移位数据?

时间:2017-04-11 15:14:06

标签: delphi

 ///Example
 some_array[0]:=0;
 some_array[1]:=1;
 some_array[2]:=2;
 some_array[3]:=3;
 some_array[4]:=4;

现在我需要像这样移动数组中的值(通过一个单元格)

 some_array[0]:=1;
 some_array[1]:=2;
 some_array[2]:=3;
 some_array[3]:=4;
 some_array[4]:=0;

是否有任何内置程序或我必须通过复制到某个临时数组手动执行此操作?

3 个答案:

答案 0 :(得分:2)

没有内置功能。你需要自己编写。它可能看起来像这样:

Errno::EACCES: Permission denied @ rb_sysopen -
C:/RailsInstaller/Ruby2.3.0/lib/ruby/gems/2.3.0/gems/nokogiri-1.7.1-x86-    mingw32/lib/nokogiri/2.3/nokogiri.so
An error occurred while installing nokogiri (1.7.1), and Bundler cannot
continue.
Make sure that `gem install nokogiri -v '1.7.1'` succeeds before bundling.

请注意,无需复制到临时阵列。您只需要制作一个元素的临时副本。

如果您的阵列很大,那么复制开销可能很大。在这种情况下,最好使用圆形阵列。使用圆形数组,您可以记住第一个元素的索引。然后,移位操作只是对该索引的简单递增或递减操作,以数组的长度为模。

如果您使用现代Delphi,那么可以很容易地将其转换为通用方法。而且我认为你应该很容易在相反的方向上写下这个转变。

答案 1 :(得分:1)

RTL中没有这样的程序。

一般程序(由@DavidHeffernan提出)可能如下所示:

Type
  TMyArray = record
    class procedure RotateLeft<T>(var a: TArray<T>); static;
  end;

class procedure TMyArray.RotateLeft<T>(var a: TArray<T>);
var
  tmp : T;
  i : Integer;
begin
  if Length(a) > 1 then begin
    tmp := a[0];
    for i := 1 to High(a) do
      a[i-1] := a[i];
    a[High(a)] := tmp;
  end;
end;

var
  a: TArray<Integer>;
  i:Integer;    
begin
  SetLength(a,5);
  for i := 0 to High(a) do a[i] := i;
  TMyArray.RotateLeft<Integer>(a);
  for i := 0 to High(a) do WriteLn(a[i]);

  ReadLn;
end.

如果性能至关重要,可以使用Move()的低级例程:

class procedure TMyArray.RotateLeft<T>(var a: TArray<T>);
var
  tmp : T;
begin
  if Length(a) > 1 then begin
    Move(a[0],tmp,SizeOf(T));          // Temporary store the first element
    Move(a[1],a[0],High(a)*SizeOf(T));
    Move(tmp,a[High(a)],SizeOf(T));    // Put first element last
    // Clear tmp to avoid ref count drop when tmp goes out of scope
    FillChar(tmp,SizeOf(T),#0);
  end;
end;

注意FillChar()调用以清除最后的临时变量。如果T是托管类型,则在超出范围时,它将丢弃最后一个数组元素的引用计数。

答案 2 :(得分:1)

在遇到类似问题时绊倒它。

我还没有实现它,但是已经考虑了这种不同的方法:保持数组原样,但是创建一个新的过程来读取更改“零”位置的值。

示例:

const url = '${window.location.origin}/assets/default/js/bundle/vue_data.bundle.js';
        this.getAxiosInstance().get(url).then(response => {
                const {Add, Edit, Filter, View} =  () => import(response.data);
        });

因此,如果使用此功能读取原始数组,则使用移位“ 1”将其读取为“ 1、2、3、4、0”(显然是循环的)。它将需要您跟踪一些事情,但不需要进行任何修改。因此,对于超大型阵列,性能应该更高。

类似类型也适用于其他类型。

编辑:带有自由开始索引和可变步长加上样本大小的示例函数在这里:

read_array(index: integer; shift: integer)..

因此:

function get_shifted_array(inArray: TStringList; startindex,
  lineCount: integer;
  stepsize: integer): TStringList;

var
   i : integer;           // temp counter
   nextindex : integer;   // calculate where to get next value from...
   arraypos  : integer;   // position in inarray to take
   temp      : tstringlist;


        // function to mimic excel Remainder( A,B) function
        // in this   remainder(-2,10) = 8
        //
           function modPositive( dividend, divisor: integer): integer;
           var
              temp : integer;

            begin

               if dividend < 0 then
                   begin
                       temp := abs(dividend) mod divisor;   // 1 mod 10 =9    for -1
                                                            // 122 mod 10 = 2  for -122
                       result :=  (divisor - temp);
                   end
               else
                  result := dividend mod divisor;
            end;


begin

   nextindex := startindex;             // where in input array to get info from
   temp := tstringlist.create;          // output placeholder

   for i := 1 to lineCount do
      begin

          // convert to actual index inside loop
          arraypos := modPositive(nextindex, inarray.count);     // handle it like Excel: remainder(-1,10) = 9

          // if mod is zero, we get array.count back. Need zero index then.
          if arraypos = inArray.Count then arraypos := 0;        // for negative loops.

          // get the value at array position
          temp.Add( 'IDX=' + inttostr(arraypos) + ' V=' +   inarray[  arraypos ] );

          // where to go next
          // should we loop ?
          if ((nextindex+ stepsize +1)> inArray.Count ) then
                 begin
                     nextindex :=  (nextindex + stepsize ) mod inArray.Count;
                 end
          else
              nextindex := nextindex + stepsize;
      end;

   result := temp;

end;

将使数组向后移一位。

全部,不对数组进行任何修改。