2016-04-06 5 views
-1

Was wäre der effizienteste Weg, um die Array-Elemente neu anzuordnen, so dass sie mit dem entsprechenden Indexwert (minus eins) geordnet sind &? Die Variable $ dat ist die maximale Anzahl von Elementen (die im Array niemals überschritten wird, aber möglicherweise vorhanden ist oder nicht vorhanden ist).Perl: Array nach Elementwert neu anordnen

$dat = 14; 
my @array = (1, 12, 14, 7, 8, 4) 

Mit anderen Worten:

my @new_array = (1, undef, undef, 4, undef, undef, 7, 8, undef, undef, undef, 12, undef, 14); 

*** EDIT **** Fuller Code-Schnipsel:

foreach $auth (keys %activity) { 
my @value = @{ $activity{$auth} }; 
@value = uniq @value; 
@value = sort @value; 
s/^0// for @value; 

my $count = scalar(grep $_, @value); 
my $dat = max(@value); 
@{$activity{$auth}} = @value; 
} 
+0

ist es immer von 1 läuft bis zu '$ dat'? – syck

+0

Werte innerhalb des Arrays können von Zeit zu Zeit abweichen (aber niemals dat überschreiten). Ich habe einige Variationen von "If" ausprobiert, aber es ist wirklich chaotisch. Ich scheine auf das Entfernen der vorhandenen Array-Index nach dem Verschieben des Wertes an seine neue Position fest – user3425900

+0

"Sortierung" sollte wahrscheinlich vor 'uniq' kommen – infixed

Antwort

-1

Sie können mit einem neuen Array erstellen:

for (my $i = @array; $i--;) { 
    my $j = $array[$i]-1; 
    if ($i < $j) { 
     $array[$j] = $j+1; 
     $array[$i] = undef; 
    } 
    elsif ($i > $j) { 
     @array[$i, $j] = @array[$j, $i]; 
     redo; 
    } 
} 

In-place (Duplikate im ursprünglichen auftreten können) alle Werte, die nach dem Finden des Maximalwerts in der ersten definiert sind, und dann in dieser neuen Matrix jeden Wert löschen, der nicht in der ersten ist:

use strict; 
use warnings; 
use Data::Dumper; 


my @array = ('1', '4', '3'); 
my $max = (sort { $b <=> $a } @array)[0]; #should be 4 

print Dumper(\@array); 

my @new_arr; 
foreach my $index (0 .. ($max - 1)) { 
    $new_arr[$index] = ($index + 1);  
     #Array should be fully populated, @new_arr = ('1', '2', '3', '4'); 
    $new_arr[$index] = 'undef' unless (grep {$_ eq $new_arr[$index]} @array); 
     #Values not in the original array should be set to undef 

} 
# @new_arr should be (''1', 'undef', '3', '4') 

print Dumper(\@new_arr); 
Output

:

$VAR1 = [ 
      '1', 
      '4', 
      '3' 
     ]; 

$VAR1 = [ 
      1, 
      'undef', 
      3, 
      4 
     ]; 
+1

Das OP hat ausdrücklich nach effizienten Lösungen gefragt, und dies ist weit weniger effizient (O (N^2)) als die zuvor eingereichten Antworten (O (N)). Das ist eine schreckliche Lösung. – ikegami

+0

Ich denke ehrlich, dass deine Lösungen auch schrecklich aussehen und ziemlich unelegant. Drei verschiedene Implementierungen für verschiedene Verwendungsbedingungen, mit verschachtelten else/if-Schleifen und i/j-Indizes ... meins funktioniert für alle Bedingungen; Entfernen der Duplikate, falls vorhanden, und Ausführen der erforderlichen Aufgabe. – jbord39

+0

Es ist sicher seltsam, wie er mir dann den grünen Check gegeben hat ... Wie kannst du sagen, dass es nicht tut, was er fragt, ich habe ein Beispiel Code-Schnipsel zusammen mit der richtigen Ausgabe oben gezeigt. Ich verstehe, dass Big-O-Notation Ihre "effizienter" ist, aber Big-O ist nicht das einzige Maß für Effizienz. Auch ich konkurriere nicht mit dir. Ich gab eine Lösung, die sein Problem löste.Auf der Grundlage Ihrer Representation bedeutet diese Seite Ihnen offensichtlich viel, und Sie können einfach nicht mit der Antwort von jemand anderem umgehen, wenn Sie den grünen Check bekommen. – jbord39

2

Einfache und schnelle (Duplikate im ursprünglichen auftreten können):

my @new_array; 
$new_array[$_ - 1] = $_ for @array; 

In-place (Duplikate nicht in Original erlaubt):

for (my $i = @array; $i--;) { 
    my $j = $array[$i]-1; 
    if ($i < $j) { 
     $array[$j] = $j+1; 
     $array[$i] = undef; 
    } 
    elsif ($i > $j) { 
     if ($array[$j] == $j+1) { 
     $array[$i] = undef; 
     } 
     else { 
     @array[$i, $j] = @array[$j, $i]; 
     redo; 
     } 
    } 
} 

pop(@array) while @array && !defined($array[-1]); 
+0

Von Kommentaren scheint es, dass der Benutzer es an Ort und Stelle tun möchte. Obwohl es die Aufgabe eher eine Art Puzzle/Golf als eher etwas realistisches machen würde. –

+0

@Oleg V. Volkov, dann fügen Sie '@array = @new_array;' – ikegami

+0

@Oleg V. Volkov, In-Place-Lösung hinzugefügt. – ikegami