-3
use strict;
use warnings;
use 5.010;

my $value;
my $key;

my %hash_keysort = (
  servlet      => 'true',
  servlet_dude => 123,
  hai          => "null",
  array        => 123
);

I want to get same output.

I tried with this package use Sort::Naturally.

Even though I am using natural sort, I am not able to get same output. Every time the key is changing.

Expected output:

servlet : true
servlet_dude : 123
hai : null
array : 123

I tried the nsort function also. I am not able get as it is keys.

I tried all sort types. I am not able resolve the problem.

I need to get keys every time in same order .But the thing is keys potions are keep on changing..Is there any logic to get keys in same order. My intention is I need to get keys without changing their potions every time.



Update

#!/usr/bin/perl

use Sort::Naturally;

use strict;
use warnings;

my $value;
my $key;

my %hash_keysort = (
    servlet      => 'true',
    servlet_dude => 123,
    hai          => "null",
    array        => [ 123, "null", "string" ]
);

for my $k ( sort keys %hash_keysort ) {
    printf "%-12s : %s\n", $k, $hash_keysort{$k};
}

Actual output

array        : ARRAY(0x8002afb8)
hai          : null
servlet      : true
servlet_dude : 123

Expected

servlet      : true
servlet_dude : 123
hai          : null
array        : 123

Updated one: #!/usr/bin/perl use strict; use warnings;

#binmode STDOUT, ":utf8";
use utf8;
use Data::Dumper;
use JSON;
use Scalar::Util 'reftype';

my $json;
  local $/; #Enable 'slurp' mode
  open my $fh, "<", "my.json";        #opening a file
  $json = <$fh>;
  close $fh;
my $data = decode_json($json);        #decodeing the json data
print "$data\n";
print Dumper($data);                  #prints HASH table
print "\n";

my $key;
my $value;
my $initialtag = '';                      #declaring the intial tag of the 
data
my $hash = {'HASH'=>9998,'ARRAY'=>9987,'SCALAR'=>9996};  # initializing the 
Hash table for opcodes

my $first_key;
my $tag_len;
my $opcode;
my $hex;
my $finalkey_opcode;
my $firstvalue;
my $input;
my $initialtag_2;
my $firstvalue_2;
my $datavalue = check_refernces($data);
if($datavalue){
    $datavalue = check_refernces($datavalue);
}
$datavalue = check_refernces($datavalue);

sub Hash_reference { my $input=shift; foreach $key (keys %$input) {

  $firstvalue = $input->{$key};                 #Acessing the value(Getting 
value from hash)
  print " the value of key $key  $value\n";
  $initialtag = $key;
}
        print "Variable is HASH\n\n";  
        $opcode=$hash->{'HASH'};             #If it is hash Getting opcode 
for object 
        print "the opcode is $opcode\n";

        my $tag_len =  length( $initialtag );          #Finding the length
  print "$tag_len\n";

  my $hex =sprintf('%04X',$tag_len);          #Converting to hexadecimal 
format
  print "$hex\n";
  my $first_key = $hex.$initialtag;           #concatenating the Intail tag 
and hexadecimal value(length of the data)
  print "$first_key\n";

  my $finalkey_opcode=$opcode.$first_key;     #concatenating the opcode and 
data 

  print "$finalkey_opcode\n";
  return $firstvalue;

        }
sub Scalar_reference
{
    print "Variable is SCALAR refernce\n";    # Not a reference
    {
            my $input=shift;
        $opcode=$hash->{'SCALAR'};             #If it is hash Getting opcode 
for object 
        print "the opcode is $opcode\n";
        my $tag_len =  length( $initialtag_2 );          #Finding the length
  print "$tag_len\n";

  my $hex =sprintf('%04X',$tag_len);          #Converting to hexadecimal 
format
  print "$hex\n";
  my $first_key = $hex.$initialtag_2;           #concatenating the Intail 
tag and hexadecimal value(length of the data)
  print "$first_key\n";
    my $finalkey_opcode=$opcode.$first_key;     #concatenating the opcode 
and data 
  print "$finalkey_opcode\n";
  return $firstvalue_2;
}
}
sub Array_refernce
{
    print "Variable is ARRAY\n\n";        # Reference to a ARRAY
}

sub code_refernce
{
    print "Variable is CODE\n\n";         # Reference to a CODE
}


sub check_refernces
{
    my $input = shift;
    my $returnvalue;
    if (ref($input)eq 'SCALAR')
  {
    Scalar_reference();
  }
    elsif (ref($input)eq 'HASH')
    {

        $returnvalue = Hash_reference($input);
         # Reference to a hash
     }
    elsif (ref($input)eq 'ARRAY')
    {
        Array_refernce();
    }
    elsif (ref($value)eq 'CODE')
    {
        code_refernce();
    }

}

Data file is: "web-app": { "servlet":
{ "servlet-name": true, "servlet-class": 123, "hai":null, "array":[123,null,"string"]

    }}

Expected output: servlet : true servlet_dude : 123 hai : null array : ARRAY(0x8002afb8)

How to get the same output.

  • 1
    Hi, I've fixed the formatting of your code. Please do it yourself in the future. – Dave Cross Sep 05 '17 at 11:13
  • What's exactly done to 'get output'? You cannot order keys in hash. – raina77ow Sep 05 '17 at 11:16
  • 1
    How are you trying to sort your hash? Showing the code you're using so that we can see what might be going wrong is necessary. – drmrgd Sep 05 '17 at 11:17
  • After seeing the updates, I don't think this is a sorting issue. You can't get the order you want by a sort. Maybe instead, load the keys into an array and iterate over them? – drmrgd Sep 05 '17 at 12:08
  • I've had to vote to close your question as it's *"unclear what you're asking"*. – Borodin Sep 05 '17 at 12:20
  • 1
    It's really unclear to me what you mean by "natural sort". The module you tried to use, Sort::Naturally, sorts strings lexically and numbers numerically. But that doesn't fit your description at all. What, to you, is a "natural sort"? – Dave Cross Sep 05 '17 at 13:01

2 Answers2

6

The elements of a Perl hash are in random order by design. You can't do anything to a hash to set the order of its contents.

What you can do is process or output the elements of a hash in a particular order. For instance

for my $k ( sort keys %hash_keysort ) {
    printf "%-12s : %s\n", $k, $hash_keysort{$k};
}

If you want any more help than this then you must improve your question. In particular you need to show the code you have used. "I tried with this package use Sort::Naturally" isn't enough information.

If you want the output in a specific order other than sorted, then the only way is to define that order separately.

my @keys = qw/ servlet servlet_dude hai array /;

for my $k ( @keys ) {
    my $v = $hash_keysort{$k};
    $v = $v->[0] if ref $v;
    printf "%-12s : %s\n", $k, $v;
}
Borodin
  • 126,100
  • 9
  • 70
  • 144
  • My problem is if you sort the hash. key should not change every time. – Dushyanth Simha Sep 05 '17 at 11:46
  • 2
    @DushyanthSimha you cannot sort a hash. You can take the keys of the hash, sort them in a specific way, and then for each of those keys output the key and the value. But that will **not change the hash**. A hash per design is not like a phone book, where entries are sorted, but rather like a bag of scrabble stones, but where you know exactly where each letter is in the bag. – simbabque Sep 05 '17 at 11:47
  • #!/usr/bin/perl use Sort::Naturally ; use strict; use warnings; my $value; my $key; my %hash_keysort = (servlet => 'true',servlet_dude => 123,hai =>"null", array => [123,"null","string"]); for my $k ( sort keys %hash_keysort ) { printf "%-12s : %s\n", $k, $hash_keysort{$k}; } actual output :array : ARRAY(0x8002afb8) hai : null servlet : true servlet_dude : 123 Expected: servlet : true servlet_dude : 123 hai : null array : 123 – Dushyanth Simha Sep 05 '17 at 11:55
  • I need to get keys every time in same order .But the thing is keys potions are keep on changing..Is there any logic to get keys in same order. My intention is I need to get keys without changing their potions every time – Dushyanth Simha Sep 05 '17 at 11:55
  • 2
    @DushyanthSimha I don't understand what you're talking about. If I run your code several times, it produces the same result every time. The only thing that changes is the stringified array reference address. – simbabque Sep 05 '17 at 12:04
  • @DushyanthSimha If you want the output in a specific order that can't be calculated, then you need to define that order separately. See the update to my answer. – Borodin Sep 05 '17 at 12:12
  • @DushyanthSimha: Where did that array come from in your comment? That's not in the original question. Please add new information by *editing your question*. Code is very difficult to read in comments. – Borodin Sep 05 '17 at 12:14
0

From the update, it no longer looks like a sorting issue. The order you are looking for is not amenable to any sort routine. Instead, if have a discrete set of keys and you want to output in that order, you can create an array to use for the iteration:

#!/usr/bin/perl
use strict;
use warnings;

my $value;
my $key;
my %hash_keysort = (servlet => 'true',servlet_dude => 123,hai =>"null", array => [123,"null","string"]);

my @wanted = qw(servlet servlet_dude hai array);
for my $k ( @wanted ) {
    printf "%-12s : %s\n", $k, $hash_keysort{$k};
}

This will allow you to always get the output in the order you want.

drmrgd
  • 733
  • 5
  • 17