Hacer coincidir una matriz con un valor dentro de una matriz de referencias - Perl

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)

preguntado el 12 de junio de 12 a las 21:06

¿Cuántos elementos contiene @dueDate? -

@dueDate contiene 3 elementos: año de cuatro dígitos, mes de dos dígitos y día de dos dígitos. -

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)... -

¿Has probado si (existe $vacaciones{@dueDate}) (no estoy 100% seguro acerca de la sintaxis en @dueDate pero prueba la función existe) -

4 Respuestas

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

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

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

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 or haz tu propia pregunta.