{"id":1018,"date":"2012-01-04T09:31:46","date_gmt":"2012-01-04T14:31:46","guid":{"rendered":"http:\/\/www.matthewgkeller.com\/blog\/?p=1018"},"modified":"2012-01-04T09:31:46","modified_gmt":"2012-01-04T14:31:46","slug":"sorting-strings-ending-in-numbers-in-perl","status":"publish","type":"post","link":"http:\/\/www.matthewgkeller.com\/blog\/2012\/01\/04\/sorting-strings-ending-in-numbers-in-perl\/","title":{"rendered":"Sorting Strings Ending In Numbers In Perl"},"content":{"rendered":"<h2>Synopsis<\/h2>\n<p>I deal with a lot of names that look like &#8220;somedumbserver2&#8221; and &#8220;somedumbserver15&#8221;. Using Perl&#8217;s default sort, &#8220;somedumbserver2&#8221; comes before &#8220;somedumbserver15&#8221; because the character &#8220;2&#8221; is greater than the character &#8220;1&#8221;, and that&#8217;s where the sort stops.\u00c2\u00a0 This sort, &#8220;snsort&#8221; or &#8220;string-number sort&#8221;, is a little wiser, and all else being equal compares the number &#8220;2&#8221; to the number &#8220;15&#8221;, and properly orders it. It&#8217;s also safe to use if some strings don&#8217;t conform to this pattern.<\/p>\n<p>I wrote this to be a Vmethod to list objects in Template Toolkit, so I kept the surrounding code intact in case anyone wants to use it as-is, but &#8220;sub sns&#8221; can be taken out and put in any Perl program, and used in conjunction with the Perl &#8220;sort&#8221; function.<\/p>\n<h2>Code<\/h2>\n<pre>$Template::Stash::LIST_OPS-&gt;{ snsort } = sub {\r\n\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0 my $list = shift;\r\n\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0 return sort sns @$list;\r\n\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0 \u00c2\u00a0\r\n\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0 sub sns {\r\n\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0 my @aparts=$a =~ \/^(\\D+)(\\d+)$\/;\r\n\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0 my @bparts=$b =~ \/^(\\D+)(\\d+)$\/;\r\n\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0 \u00c2\u00a0\r\n\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0 return $a cmp $b unless @aparts and @bparts; # Safety\r\n\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0 return $aparts[0] cmp $bparts[0] unless $aparts[0] eq $bparts[0];\r\n\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0 return $aparts[1] &lt;=&gt; $bparts[1];\r\n\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0 }\r\n};<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Synopsis I deal with a lot of names that look like &#8220;somedumbserver2&#8221; and &#8220;somedumbserver15&#8221;. Using Perl&#8217;s default sort, &#8220;somedumbserver2&#8221; comes before &#8220;somedumbserver15&#8221; because the character &#8220;2&#8221; is greater than the character &#8220;1&#8221;, and that&#8217;s where the sort stops.\u00c2\u00a0 This sort, &hellip; <a href=\"http:\/\/www.matthewgkeller.com\/blog\/2012\/01\/04\/sorting-strings-ending-in-numbers-in-perl\/\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5,10],"tags":[99,71,98],"class_list":["post-1018","post","type-post","status-publish","format-standard","hentry","category-general-coding","category-linuxy","tag-catalyst","tag-perl","tag-template-toolkit"],"_links":{"self":[{"href":"http:\/\/www.matthewgkeller.com\/blog\/wp-json\/wp\/v2\/posts\/1018","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/www.matthewgkeller.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.matthewgkeller.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.matthewgkeller.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.matthewgkeller.com\/blog\/wp-json\/wp\/v2\/comments?post=1018"}],"version-history":[{"count":0,"href":"http:\/\/www.matthewgkeller.com\/blog\/wp-json\/wp\/v2\/posts\/1018\/revisions"}],"wp:attachment":[{"href":"http:\/\/www.matthewgkeller.com\/blog\/wp-json\/wp\/v2\/media?parent=1018"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.matthewgkeller.com\/blog\/wp-json\/wp\/v2\/categories?post=1018"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.matthewgkeller.com\/blog\/wp-json\/wp\/v2\/tags?post=1018"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}