Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Get longest and shortest lengths of list values #8

Open
LadyAleena opened this issue Sep 15, 2020 · 15 comments
Open

Get longest and shortest lengths of list values #8

LadyAleena opened this issue Sep 15, 2020 · 15 comments

Comments

@LadyAleena
Copy link

Hello,

I was wondering if there might be any interest in users being able to get the longest and shortest lengths of list values. For example, if there is a list where the longest value is 10 characters, a user could apply a printf to the values to make every value length 10 while printing them out. If the shortest value length is 4, the user might want to substr the rest of the values to 4. Who knows where this could be useful to someone.

Note, I wrote this as a module for something I was doing, however, I think it would be better served to be part of an established module. I also do not know if the code will need tweaking.

package List::Value::Length;
use v5.8.8;
use strict;
use warnings;
use Exporter qw(import);

our $VERSION   = '1.0';
our @EXPORT_OK = qw(longest_value shortest_value longest_length shortest_length);

sub longest_length {
  my $longest_length = 0;
  for my $item (@_) {
    $longest_length = length($item) if ( !$longest_length || length($item) > $longest_length );
  }
  return $longest_length;
}

sub shortest_length {
  my $shortest_length = 0;
  for my $item (@_) {
    $shortest_length = length($item) if ( !$shortest_length || length($item) < $shortest_length );
  }
  return $shortest_length;
}

sub longest_value {
  my $longest_length = longest_length(@_);
  my $long_list;
  for my $item (@_) {
    push @$long_list, $item if length($item) == $longest_length;
  }
  return $long_list;
}

sub shortest_value {
  my $shortest_length = shortest_length(@_);
  my $short_list;
  for my $item (@_) {
    push @$short_list, $item if length($item) == $shortest_length;
  }
  return $short_list;
}

=pod

=encoding utf8

=head1 NAME

B<List::Value::Length> returns the length of the longest or shortest value or the longest or shortest value(s) on the list.

=head1 VERSION

This document describes List::Value::Length version 1.0.

=head1 SYNOPSIS

  use List::Value::Length qw(longest_length shortest_length longest_value shortest_value);

  my @colors = ('red', 'orange', 'yellow', 'spring', 'green', 'teal', 'cyan', 'azure',
                'blue', 'violet', 'magenta', 'pink', 'white', 'black', 'gray');

  my $longest_length = longest_length(@colors);
  # 7

  my $shortest_length = shortest_length(@colors);
  # 3

  my $longest_values = longest_value(@colors);
  # [ 'magenta' ]

  my $shortest_values = shortest_value(@colors);
  # [ 'red' ]

=head1 DESCRIPTION

=head2 longest_length

C<longest_length> returns the longest integer length of the values of an array.

=head2 shortest_length

C<shortest_length> returns the shortest integer length of the values of an array.

=head2 longest_value

C<longest_value> returns an arrayref with all the values that are the longest length.

=head2 shortest_value

C<shortest_value> returns an arrayref with all the values that are the shortest length.

=head1 DEPENDENCY

List::Value::Length depends on L<Exporter>.

=head1 AUTHOR

Lady Aleena

=cut

1;
@LadyAleena
Copy link
Author

It appears there is no interest in adding this to List::SomeUtils, so I will close it.

@autarch
Copy link
Member

autarch commented Oct 8, 2020

I'll reopen. I'm interested in adding this, I've just had a lot of personal life stuff to deal with recently.

One thing I'd note is that everything in this package needs both Perl and XS implementations. The latter goes in List::SomeUtils::XS.

@autarch autarch reopened this Oct 8, 2020
@LadyAleena
Copy link
Author

LadyAleena commented Oct 8, 2020

I know nothing about XS coding.

Edit: I just looked into XS coding and got lost.

@autarch
Copy link
Member

autarch commented Oct 9, 2020

Yeah, XS is a challenge. I want to leave this issue open in case someone else (including me) wants to give this a shot in the future.

@LadyAleena
Copy link
Author

I would give XS my attention, however, until I get my first module packaged and released successfully; I do not have the confidence to learn anything else.

@LadyAleena
Copy link
Author

I just looked at List::SomeUtils::XS and the source does not have anything for me to study.

@autarch
Copy link
Member

autarch commented Oct 11, 2020

XS code is in .xs files. See https://github.com/houseabsolute/List-SomeUtils-XS/blob/master/XS.xs for the interesting bits.

@LadyAleena
Copy link
Author

My eyes just crossed looking at that. Is there a reason behind the XS implementation?

@autarch
Copy link
Member

autarch commented Oct 11, 2020

XS is a way to write code that in C that can be used by Perl code, and/or to write code that interfaces with C libraries. In this case, there's no external library being used, it's just used because it's a fair bit faster.

A lot of what it's doing is just calling the Perl C API, which can be a lot faster than doing the equivalent operations in pure Perl.

@LadyAleena
Copy link
Author

LadyAleena commented Oct 11, 2020

I rewrote the POD from above to be copied and pasted into the POD for SomeUtils. I looked over the other functions in the module and did not see justifications for the others. However, if you are interested in possible reasons to use these, I can write it up for the POD or just for your amusement. That is if I hadn't explained the reason already. The head2 List value lengths is the best heading name I could come up with for now.

Note, I tried to stay within the 80 character line length limit, but some lines are a tad longer than 80 characters. I am of the opinion the 80 character line length limit is a little outdated, but I tried to keep the lines short. 🙂

=head2 List value lengths

  my @colors = ('red', 'orange', 'yellow', 'spring', 'green', 'teal',
                'cyan', 'azure', 'blue', 'violet', 'magenta', 'pink',
                'white', 'black', 'gray');

=head3 longest_length

  my $longest_length = longest_length(@colors);

C<longest_length> returns the longest integer length of the values of an array.
It will return C<7> for the above example.

=head3 shortest_length

  my $shortest_length = shortest_length(@colors);

C<shortest_length> returns the shortest integer length of the values of an array.
It will return C<3> for the above example.

=head3 longest_value

  my $longest_values = longest_value(@colors);

C<longest_value> returns an arrayref with all the values that are the longest length.
It will return the following for the preceding example.

  [ 'magenta' ]

=head3 shortest_value

  my $shortest_values = shortest_value(@colors);

C<shortest_value> returns an arrayref with all the values that are the shortest length.
It will return the following for the preceding example.

  [ 'red' ]

@LadyAleena
Copy link
Author

LadyAleena commented Oct 11, 2020

Here are some tests written that go with the above POD using Test::More.

my @colors = ('red', 'orange', 'yellow', 'spring', 'green', 'teal', 'cyan', 'azure',
              'blue', 'violet', 'magenta', 'pink', 'white', 'black', 'gray');

is(
  List::Value::Length::longest_length(@colors),
  '7',
  "testing longest_length for array @colors is 7"
);

is(
  List::Value::Length::shortest_length(@colors),
  '3',
  "testing shortest_length for array @colors is 3"
);

is_deeply(
  List::Value::Length::longest_value(@colors),
  [ 'magenta' ],
  "testing longest_value is magenta only"
);

is_deeply(
  List::Value::Length::shortest_value(@colors),
  [ 'red' ],
  "testing shortest_value is red only"
);

@shlomif
Copy link

shlomif commented Oct 11, 2020

I may be able to help with writing the XS code (I am versed in writing C and have some basic XS skills). Some comments:

  1. I could use more test assertions.

  2. longest_value and shortest_value should be titled in plural in my opinion.

  3. Should they return lists instead of array refs?

@LadyAleena
Copy link
Author

  1. Do you mean another list to test against?
  2. Here are the plurals:
sub longest_values {
  longest_value(@_);
}
 
sub shortest_values
  shortest_value(@_);
}
  1. You are right, they should return lists not array references.
sub longest_value {
  my $longest_length = longest_length(@_);
  my @long_list;
  for my $item (@_) {
    push @long_list, $item if length($item) == $longest_length;
  }
  return @long_list;
}

sub shortest_value {
  my $shortest_length = shortest_length(@_);
  my @short_list;
  for my $item (@_) {
    push @short_list, $item if length($item) == $shortest_length;
  }
  return @short_list;
}

So the tests would be...

is_deeply(
  [ List::Value::Length::longest_value(@colors) ],
  [ 'magenta' ],
  "testing longest_value is magenta only"
);

is_deeply(
  [ List::Value::Length::shortest_value(@colors) ],
  [ 'red' ],
  "testing shortest_value is red only"
);

In the documentation, replace arrayref with array or list.

@shlomif
Copy link

shlomif commented Oct 12, 2020

1. Do you mean another list to test against?

Kind-of. Test assertions are jargon for calls to checks such as is() is_deeply, cmp_ok, or ok(). https://en.wikipedia.org/wiki/Test_assertion . I meant that you should add more such checks.

2. Here are the plurals:
sub longest_values {
  longest_value(@_);
}
 
sub shortest_values
  shortest_value(@_);
}

Well, naming them in singular is misleading - I think you should not define two functions with nearly identical names (which is Feature creep ).

1. You are right, they should return lists not array references.

I see, thanks!

sub longest_value {
  my $longest_length = longest_length(@_);
  my @long_list;
  for my $item (@_) {
    push @long_list, $item if length($item) == $longest_length;
  }
  return @long_list;
}

sub shortest_value {
  my $shortest_length = shortest_length(@_);
  my @short_list;
  for my $item (@_) {
    push @short_list, $item if length($item) == $shortest_length;
  }
  return @short_list;
}

So the tests would be...

is_deeply(
  [ List::Value::Length::longest_value(@colors) ],
  [ 'magenta' ],
  "testing longest_value is magenta only"
);

is_deeply(
  [ List::Value::Length::shortest_value(@colors) ],
  [ 'red' ],
  "testing shortest_value is red only"
);

In the documentation, replace arrayref with array or list.

Furthermore, another question: should the {longest,shortest}_length functions return undef upon being given an empty list as input rather than 0 in accordance with the behaviour of max() and min() ?

@ikegami
Copy link

ikegami commented Dec 8, 2022

In the array ref versions, undef is returned rather than an array ref if no arguments are passed. This is a pitfall.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

4 participants