Hacer coincidir una matriz con un valor dentro de una matriz de referencias - Perl
Frecuentes
Visto 159 veces
4
Tengo la siguiente matriz de referencias a matrices:
my @holidays = [[2012,'01','02'],[2012,'01','16'],[2012,'02','20'],[2012,'04','16'],[2012,'05','28'],[2012,'07','04'],[2012,'09','03'],[2012,'10','08'],[2012,'11','12'],[2012,'11','22'],[2012,'12','25']];
Cuáles son los feriados legales reconocidos por el IRS durante 2012. Me gustaría hacer coincidir la matriz @dueDate con un valor en esa matriz y devolver 1 o verdadero si está presente.
while ($holidays[@dueDate]){
print ("Found Holiday \t join('-',@dueDate)");
@dueDate = Add_Delta_Days(@dueDate, 1);
if ( Day_of_Week(@dueDate) > 5){
@dueDate = Monday_of_Week((Week_Number(@dueDate)+1), $dueDate[0]);
}
}
Es mi intento actual de esto: la condición de la declaración while nunca es cierta. He probado algunas combinaciones diferentes de referencias y desreferencias de vacaciones sin éxito.
¿Cuál sería la mejor manera de manipular la evaluación dentro de la declaración while de modo que el bloque se ejecute cuando @dueDate contenga una fecha dentro de mi matriz anterior?
Nota: @dueDate es una matriz estándar Date::Calc - (Año, Mes, Día)
4 Respuestas
3
Esto debería ponerte en el camino correcto. Veo dos problemas con su código: una matriz de matrices debe tener paréntesis normales en la parte exterior y usar el operador ~~ para comparar matrices en busca de igualdad.
my @holidays = ([2012,'01','02'],[2012,'01','16'],[2012,'02','20'],[2012,'04','16'],
[2012,'05','28'],[2012,'07','04'],[2012,'09','03'],[2012,'10','08'],[2012,'11','12'],
[2012,'11','22'],[2012,'12','25']);
my $i;
my @duedate = [2012, '01', '02'];
for ($i = 0; $i < @holidays; $i++)
{
if (@holidays[$i] ~~ @duedate)
{
print "matched!!";
}
}
Respondido el 12 de junio de 12 a las 22:06
Usé esto con el ciclo for de @fxzuz. Gracias por la ayuda. Sabía que estaba haciendo algo mal con la sintaxis de la matriz. - voto
hum, veo que aceptaste esta solución. Tenga en cuenta que es bastante ineficiente. Tiene que comprobar cada @holiday para encontrar una coincidencia. Esas son operaciones O(N). El mío es O(1). No importa cuántos días festivos tenga, solo se necesita una verificación para ver si una fecha es un día festivo. - Ikegami
2
En primer lugar,
my @holidays = [[2012,'01','02'],...,[2012,'12','25']];
debiera ser
my @holidays = ([2012,'01','02'],...,[2012,'12','25']);
Estás creando una matriz con un solo elemento.
Probablemente la mejor manera de lograr lo que quieres es usar un hash.
my %holidays = map { join('-', @$_) => 1 } @holidays;
Entonces todo lo que necesitas es
while ($holidays{join('-', @dueDate)}) {
my $dow = Day_of_Week(@dueDate);
@dueDate = Add_Delta_Days(@dueDate,
$dow == 5 || $dow == 6 ? 8 - $dow : 1);
}
Respondido el 12 de junio de 12 a las 22:06
2
Esta es mi respuesta, trabajando en Perl 5.14, también uso el operador ~~ de coincidencia inteligente para comparar dos matrices.
Usted asigna a la matriz @vacaciones = [[2012,'01','02'], ]; no es correcto, en realidad asigna una matriz anónima [['2012', '01', '02'], ] al primer elemento de @holidays.
use v5.14;
my @holidays = ( ['2012', '01', '02'], ['2012', '01', '16'] );
my @due_date = ( '2012', '01', '16' );
for my $holiday (@holidays) {
if (@$holiday ~~ @due_date) {
say "holiday match";
}
}
Respondido el 12 de junio de 12 a las 22:06
0
De acuerdo, algunas cosas:
1: Las listas se encuentran entre paréntesis y las referencias de matrices literales se escriben entre corchetes. Entonces, deberías tener:
my @holidays = ([2012,'01','02'],[2012,'01','16'],[2012,'02','20'],[2012,'04','16'],[2012,'05','28'],
[2012,'07','04'],[2012,'09','03'],[2012,'10','08'],[2012,'11','12'],[2012,'11','22'],[2012,'12','25']);
2: cuando miras $holidays[@dueDate]
, estás llamando a todo contexto escalar. En particular, desde @dueDate
tiene tres elementos, solo estás mirando $holidays[3]
.
3: a menos que esté escribiendo un código desechable, siempre use strict;
y use warnings;
.
Entonces, quieres algo como esto:
use strict;
use warnings;
my @holidays = ([2012,'01','02'],[2012,'01','16'],[2012,'02','20'],[2012,'04','16'],[2012,'05','28'],
[2012,'07','04'],[2012,'09','03'],[2012,'10','08'],[2012,'11','12'],[2012,'11','22'],[2012,'12','25']);
my @dueDates=([2012,'01','01'],[2012,'01','02'],[2012,'01','03']); #Or whatever
my @due_dates_that_are_holidays=();
foreach my $due_date(@dueDates)
{
foreach my $holiday(@holidays)
{
my ($h_y,$h_m,$h_d)=@$holiday; #Capturing year month and day from the array reference
my ($d_y,$d_m,$d_d)=@$due_date; #Ditto for the due date
if($h_y == $d_y and $h_m eq $d_m and $h_d eq $d_d)
{
push @due_dates_that_are_holidays,$due_date;
}
}
}
print join("-",@{$_}) . "\n" foreach(@due_dates_that_are_holidays);
El código anterior produce el siguiente resultado:
2012-01-02
Respondido el 12 de junio de 12 a las 22:06
Este es un fragmento de un programa mucho más grande: se incluyeron advertencias y estrictas. - voto
No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas arrays perl date reference dereference or haz tu propia pregunta.
¿Cuántos elementos contiene @dueDate? - Girish Rao
@dueDate contiene 3 elementos: año de cuatro dígitos, mes de dos dígitos y día de dos dígitos. - voteblake
Así es como se muestran las dos variables en el depurador de Eclipse al invocar la instrucción while: fecha de vencimiento... [0] 2012 [1] 1 [2] 11 @vacaciones... [0] ARRAY(0x3567c78).. [0] ARRAY(0x356a4f0)... [0] 2012 [1] 01 [2] 02 [1] ARRAY(0x379d4f0)... [2] ARRAY(0x356b898)... [3] ARRAY(0x3567948) ... [4] MATRIZ(0x2a846d8)... [5] MATRIZ(0x356bf88)... [6] MATRIZ(0x2a84738)... [7] MATRIZ(0x356bda8)... [8] MATRIZ(0x356b880) ... [9] ARREGLO(0x356b8c8)... [10] ARREGLO(0x356bd60)... - voteblake
¿Has probado si (existe $vacaciones{@dueDate}) (no estoy 100% seguro acerca de la sintaxis en @dueDate pero prueba la función existe) - Girish Rao