Stringify Struct in Perl

113 views Asked by At

In my program, I have a section of code that updates a list box depending on the value of another list box.

The code that does this looks a little like this.

$listBox1->bind('<<ListboxSelect>>' => sub {
    $listBox2->delete(0, 'end');
    for(@{$hashOfArraysOfStruct{$listBox1->get($listBox1->curselection)}}) {
        $listBox2->insert('end', $_->name);
    }
});

enter image description here

This works fine. However, I have found it easier to simply use a list and manipulate the list on the <<ListboxSelect>>. I have bound this list to the list box using -listvariable.

The code to do this looks a bit like

$listBox1->bind('<<ListboxSelect>>' => sub {
    @updateableList = @{$hashOfArraysOfStruct{$listBox1->get($listBox1->curselection)}};
});

enter image description here

The problem with this approach is, as hashOfArraysOfStruct, contains structures, the list box contains values such as MyStruct=HASH(0x31d7e3c).

Is there any way to display the name variable of the struct MyStruct without looping through the whole array and individually inserting each result into the list box?


MCVE

use strict;
use warnings;
use Tk;
use Class::Struct;

struct MyStruct => {
    name => '$',
    group => '$'
};

my %hashOfArraysOfStruct = (
    A => [ 
        MyStruct->new(name => 'Phil', group => 'A'),
        MyStruct->new(name => 'Ian', group => 'A'),
        MyStruct->new(name => 'George', group => 'A')
    ],
    B => [ 
        MyStruct->new(name => 'Mac', group => 'B'),
        MyStruct->new(name => 'Will', group => 'B')
    ],
    C => [ 
        MyStruct->new(name => 'Cath', group => 'C'),
        MyStruct->new(name => 'Thom', group => 'C'),
        MyStruct->new(name => 'Richard', group => 'C'),
        MyStruct->new(name => 'Paul', group => 'C'),
        MyStruct->new(name => 'Nick', group => 'C')
    ]
);

my $mainWindow = MainWindow->new();

my @listOne = sort(keys %hashOfArraysOfStruct);

############################################
#Route One
#Less efficient as has to loop through all the values
#But it displays the name variable of MyStruct
my $listBox1 = $mainWindow->Scrolled("Listbox", -scrollbars => "osoe", -selectmode => "single", -listvariable => \@listOne)->pack;
my $listBox2 = $mainWindow->Scrolled("Listbox", -scrollbars => "osoe", -selectmode => "single")->pack;

$listBox1->bind('<<ListboxSelect>>' => sub {
    $listBox2->delete(0, 'end');
    for(@{$hashOfArraysOfStruct{$listBox1->get($listBox1->curselection)}}) {
        $listBox2->insert('end', $_->name);
    }
});
############################################

############################################
#Route Two
#Works but displays in the form of MyStruct=HASH(0x31d7e3c)
#my @updateableList;
#my $listBox1 = $mainWindow->Scrolled("Listbox", -scrollbars => "osoe", -selectmode => "single", -listvariable => \@listOne)->pack;
#my $listBox2 = $mainWindow->Scrolled("Listbox", -scrollbars => "osoe", -selectmode => "single", -listvariable => \@updateableList)->pack;

#$listBox1->bind('<<ListboxSelect>>' => sub {
#   @updateableList = @{$hashOfArraysOfStruct{$listBox1->get($listBox1->curselection)}};
#});
############################################

############################################
#What I would like to happen
#I would like to use route two but when the struct is displayed
#in the list box, instead of being in Route Twos format, it should
#display the name variable of MyStruct.
############################################

MainLoop;
1

There are 1 answers

1
JGNI On BEST ANSWER

Massive Edit

Change

@updateableList = @{$hashOfArraysOfStruct{$listBox1->get($listBox1->curselection)}};

to

@updateableList = map { $_->name() } @{$hashOfArraysOfStruct{$listBox1->get($listBox1->curselection)}};

To extract the list of names from the list of structs;