Sort a list of object identifiers: Difference between revisions
(Added example TCL entry) |
(Add Common Lisp implementation) |
||
Line 101: | Line 101: | ||
1.3.6.1.4.1.11150.3.4.0.1 |
1.3.6.1.4.1.11150.3.4.0.1 |
||
</pre> |
</pre> |
||
=={{header|Common Lisp}}== |
|||
<lang lisp>(defun oid->list (oid) |
|||
(loop for start = 0 then (1+ pos) |
|||
for pos = (position #\. oid :start start) |
|||
collect (parse-integer oid :start start :end pos) |
|||
while pos)) |
|||
(defun list< (list1 list2) |
|||
(loop for e1 in list1 |
|||
for e2 in list2 |
|||
do (cond ((< e1 e2) |
|||
(return t)) |
|||
((> e1 e2) |
|||
(return nil))) |
|||
finally (return (< (length list1) (length list2))))) |
|||
(defun sort-oids (oids) |
|||
(sort oids #'list< :key #'oid->list)) |
|||
(defun main () |
|||
(let ((oids (list "1.3.6.1.4.1.11.2.17.19.3.4.0.10" |
|||
"1.3.6.1.4.1.11.2.17.5.2.0.79" |
|||
"1.3.6.1.4.1.11.2.17.19.3.4.0.4" |
|||
"1.3.6.1.4.1.11150.3.4.0.1" |
|||
"1.3.6.1.4.1.11.2.17.19.3.4.0.1" |
|||
"1.3.6.1.4.1.11150.3.4.0"))) |
|||
(dolist (oid (sort-oids oids)) |
|||
(write-line oid))))</lang> |
|||
{{out}} |
|||
<pre>1.3.6.1.4.1.11.2.17.5.2.0.79 |
|||
1.3.6.1.4.1.11.2.17.19.3.4.0.1 |
|||
1.3.6.1.4.1.11.2.17.19.3.4.0.4 |
|||
1.3.6.1.4.1.11.2.17.19.3.4.0.10 |
|||
1.3.6.1.4.1.11150.3.4.0 |
|||
1.3.6.1.4.1.11150.3.4.0.1</pre> |
|||
=={{header|Elixir}}== |
=={{header|Elixir}}== |
Revision as of 23:13, 3 March 2017
You are encouraged to solve this task according to the task description, using any language you may know.
Object identifiers (OID) are strings used to identify objects in network data.
Show how to sort a list of OIDs, in their natural sort order.
- An OID consists of one or more non-negative integers in base 10, separated by dots. It starts and ends with a number.
- Their natural sort order is lexicographical with regard to the dot-separated fields, using numeric comparison between fields.
Input (list of strings) | Output (list of strings) |
---|---|
|
|
C++
<lang Cpp>#include <string>
- include <vector>
- include <algorithm>
- include <boost/tokenizer.hpp>
- include <iostream>
std::vector<std::string> splitOnChar ( std::string & s , const char c ) {
typedef boost::tokenizer<boost::char_separator<char>> tokenizer ; std::vector<std::string> parts ; boost::char_separator<char> sep( &c ) ; tokenizer tokens( s , sep ) ; for ( auto it = tokens.begin( ) ; it != tokens.end( ) ; it++ ) parts.push_back( *it ) ; return parts ;
}
bool myCompare ( const std::string & s1 , const std::string & s2 ) {
std::string firstcopy( s1 ) ; std::string secondcopy ( s2 ) ; std::vector<std::string> firstparts( splitOnChar ( firstcopy, '.' ) ) ; std::vector<std::string> secondparts( splitOnChar ( secondcopy, '.' ) ) ; std::vector<int> numbers1( firstparts.size( ) ) ; std::vector<int> numbers2( secondparts.size( ) ) ; std::transform( firstparts.begin( ) , firstparts.end( ) , numbers1.begin( ) ,
[]( std::string st ) { return std::stoi( st , nullptr ) ; } ) ;
std::transform( secondparts.begin( ) , secondparts.end( ) , numbers2.begin( ) ,
[]( std::string st ) { return std::stoi( st , nullptr ) ; } ) ;
auto it1 = numbers1.begin( ) ; auto it2 = numbers2.begin( ) ; while ( *it1 == *it2 ) { it1++ ; it2++ ; } if ( it1 == numbers1.end( ) || it2 == numbers2.end( ) ) return std::lexicographical_compare( s1.begin( ) , s1.end( ) , s2.begin( ) , s2.end( ) ) ; return *it1 < *it2 ;
}
int main( ) {
std::vector<std::string> arrayOID { "1.3.6.1.4.1.11.2.17.19.3.4.0.10" , "1.3.6.1.4.1.11.2.17.5.2.0.79" , "1.3.6.1.4.1.11.2.17.19.3.4.0.4" , "1.3.6.1.4.1.11150.3.4.0.1" , "1.3.6.1.4.1.11.2.17.19.3.4.0.1" , "1.3.6.1.4.1.11150.3.4.0" } ; std::sort( arrayOID.begin( ) , arrayOID.end( ) , myCompare ) ; for ( std::string s : arrayOID ) std::cout << s << '\n' ; return 0 ;
}</lang>
- Output:
1.3.6.1.4.1.11.2.17.5.2.0.79 1.3.6.1.4.1.11.2.17.19.3.4.0.1 1.3.6.1.4.1.11.2.17.19.3.4.0.4 1.3.6.1.4.1.11.2.17.19.3.4.0.10 1.3.6.1.4.1.11150.3.4.0 1.3.6.1.4.1.11150.3.4.0.1
Common Lisp
<lang lisp>(defun oid->list (oid)
(loop for start = 0 then (1+ pos) for pos = (position #\. oid :start start) collect (parse-integer oid :start start :end pos) while pos))
(defun list< (list1 list2)
(loop for e1 in list1 for e2 in list2 do (cond ((< e1 e2) (return t)) ((> e1 e2) (return nil))) finally (return (< (length list1) (length list2)))))
(defun sort-oids (oids)
(sort oids #'list< :key #'oid->list))
(defun main ()
(let ((oids (list "1.3.6.1.4.1.11.2.17.19.3.4.0.10" "1.3.6.1.4.1.11.2.17.5.2.0.79" "1.3.6.1.4.1.11.2.17.19.3.4.0.4" "1.3.6.1.4.1.11150.3.4.0.1" "1.3.6.1.4.1.11.2.17.19.3.4.0.1" "1.3.6.1.4.1.11150.3.4.0"))) (dolist (oid (sort-oids oids)) (write-line oid))))</lang>
- Output:
1.3.6.1.4.1.11.2.17.5.2.0.79 1.3.6.1.4.1.11.2.17.19.3.4.0.1 1.3.6.1.4.1.11.2.17.19.3.4.0.4 1.3.6.1.4.1.11.2.17.19.3.4.0.10 1.3.6.1.4.1.11150.3.4.0 1.3.6.1.4.1.11150.3.4.0.1
Elixir
<lang elixir>defmodule Sort_by_OID do
def numbers(list) do Enum.sort_by(list, fn oid -> String.split(oid, ".") |> Enum.map(&String.to_integer/1) end) end
end
~w[
1.3.6.1.4.1.11.2.17.19.3.4.0.10 1.3.6.1.4.1.11.2.17.5.2.0.79 1.3.6.1.4.1.11.2.17.19.3.4.0.4 1.3.6.1.4.1.11150.3.4.0.1 1.3.6.1.4.1.11.2.17.19.3.4.0.1 1.3.6.1.4.1.11150.3.4.0
] |> Sort_by_OID.numbers |> Enum.each(fn oid -> IO.puts oid end)</lang>
- Output:
1.3.6.1.4.1.11.2.17.5.2.0.79 1.3.6.1.4.1.11.2.17.19.3.4.0.1 1.3.6.1.4.1.11.2.17.19.3.4.0.4 1.3.6.1.4.1.11.2.17.19.3.4.0.10 1.3.6.1.4.1.11150.3.4.0 1.3.6.1.4.1.11150.3.4.0.1
Haskell
<lang Haskell>import Data.List ( sort , intercalate )
splitString :: Eq a => (a) -> [a] -> a splitString c [] = [] splitString c s = let ( item , rest ) = break ( == c ) s
( _ , next ) = break ( /= c ) rest
in item : splitString c next
convertIntListToString :: [Int] -> String convertIntListToString = intercalate "." . map show
orderOID :: [String] -> [String] orderOID = map convertIntListToString . sort . map ( map read . splitString '.' )
oid :: [String] oid = ["1.3.6.1.4.1.11.2.17.19.3.4.0.10" ,
"1.3.6.1.4.1.11.2.17.5.2.0.79" , "1.3.6.1.4.1.11.2.17.19.3.4.0.4" , "1.3.6.1.4.1.11150.3.4.0.1" , "1.3.6.1.4.1.11.2.17.19.3.4.0.1" , "1.3.6.1.4.1.11150.3.4.0"]
main :: IO ( ) main = do
mapM_ putStrLn $ orderOID oid</lang>
- Output:
3.6.1.4.1.11.2.17.5.2.0.79 3.6.1.4.1.11.2.17.19.3.4.0.1 3.6.1.4.1.11.2.17.19.3.4.0.4 3.6.1.4.1.11.2.17.19.3.4.0.10 3.6.1.4.1.11150.3.4.0 3.6.1.4.1.11150.3.4.0.1
(To use split :: (Char -> Bool) -> Text -> [Text] in the standard libraries, we would have to temporarily convert the strings from [Char] to Text with pack and unpack)
<lang haskell>import Data.Text (pack, split, unpack) import Data.List (sort, intercalate)
-- SORTING OBJECT IDENTIFIERS ------------------------------------------------ oidSort :: [String] -> [String] oidSort =
(intercalate "." <$>) . ((show <$>) <$>) . sort . (((readInt <$>) . splitString '.') <$>)
-- GENERIC FUNCTIONS --------------------------------------------------------- splitString :: Char -> String -> [String] splitString c s = unpack <$> split (c ==) (pack s)
readInt :: String -> Int readInt xs = read xs :: Int
-- TEST ---------------------------------------------------------------------- main :: IO () main =
mapM_ putStrLn $ oidSort [ "1.3.6.1.4.1.11.2.17.19.3.4.0.10" , "1.3.6.1.4.1.11.2.17.5.2.0.79" , "1.3.6.1.4.1.11.2.17.19.3.4.0.4" , "1.3.6.1.4.1.11150.3.4.0.1" , "1.3.6.1.4.1.11.2.17.19.3.4.0.1" , "1.3.6.1.4.1.11150.3.4.0" ]</lang>
- Output:
1.3.6.1.4.1.11.2.17.5.2.0.79 1.3.6.1.4.1.11.2.17.19.3.4.0.1 1.3.6.1.4.1.11.2.17.19.3.4.0.4 1.3.6.1.4.1.11.2.17.19.3.4.0.10 1.3.6.1.4.1.11150.3.4.0 1.3.6.1.4.1.11150.3.4.0.1
Where Data.List.Split is available (https://hackage.haskell.org/package/split-0.2.3.1/docs/Data-List-Split.html) we can alternatively write:
<lang haskell>import Data.List.Split (splitOn) import Data.List (sort, intercalate)
-- SORTING OBJECT IDENTIFIERS ------------------------------------------------ oidSort :: [String] -> [String] oidSort =
(intercalate "." <$>) . fmap (show <$>) . sort . fmap (fmap readInt . splitOn ".")
readInt :: String -> Int readInt x = read x :: Int</lang>
J
Data:
<lang J>oids=:<@-.&' ';._2]0 :0
1.3.6.1.4.1.11.2.17.19.3.4.0.10 1.3.6.1.4.1.11.2.17.5.2.0.79 1.3.6.1.4.1.11.2.17.19.3.4.0.4 1.3.6.1.4.1.11150.3.4.0.1 1.3.6.1.4.1.11.2.17.19.3.4.0.1 1.3.6.1.4.1.11150.3.4.0
)</lang>
In other words, for each line in that script, remove the spaces and put the rest in a box.
Sorting:
<lang J> >(/: __&".;._1&.('.'&,)&>) oids 1.3.6.1.4.1.11.2.17.5.2.0.79 1.3.6.1.4.1.11.2.17.19.3.4.0.1 1.3.6.1.4.1.11.2.17.19.3.4.0.4 1.3.6.1.4.1.11.2.17.19.3.4.0.10 1.3.6.1.4.1.11150.3.4.0 1.3.6.1.4.1.11150.3.4.0.1 </lang>
In other words, for our sort key, we break the contents of each box by an initial '.' and treat the remainder as numbers.
We also pull the result out of its boxes for display purposes.
Kotlin
<lang scala>// version 1.0.6
class Oid(val id: String): Comparable<Oid> {
override fun compareTo(other: Oid): Int { val splits1 = this.id.split('.') val splits2 = other.id.split('.') val minSize = if (splits1.size < splits2.size) splits1.size else splits2.size for (i in 0 until minSize) { if (splits1[i].toInt() < splits2[i].toInt()) return -1 else if (splits1[i].toInt() > splits2[i].toInt()) return 1 } return splits1.size.compareTo(splits2.size) }
override fun toString() = id
}
fun main(args: Array<String>) {
val oids = arrayOf( Oid("1.3.6.1.4.1.11.2.17.19.3.4.0.10"), Oid("1.3.6.1.4.1.11.2.17.5.2.0.79"), Oid("1.3.6.1.4.1.11.2.17.19.3.4.0.4"), Oid("1.3.6.1.4.1.11150.3.4.0.1"), Oid("1.3.6.1.4.1.11.2.17.19.3.4.0.1"), Oid("1.3.6.1.4.1.11150.3.4.0") ) println(oids.sorted().joinToString("\n"))
}</lang>
- Output:
1.3.6.1.4.1.11.2.17.5.2.0.79 1.3.6.1.4.1.11.2.17.19.3.4.0.1 1.3.6.1.4.1.11.2.17.19.3.4.0.4 1.3.6.1.4.1.11.2.17.19.3.4.0.10 1.3.6.1.4.1.11150.3.4.0 1.3.6.1.4.1.11150.3.4.0.1
Lua
Using the in-built table.sort with a custom compare function. <lang Lua>local OIDs = {
"1.3.6.1.4.1.11.2.17.19.3.4.0.10", "1.3.6.1.4.1.11.2.17.5.2.0.79", "1.3.6.1.4.1.11.2.17.19.3.4.0.4", "1.3.6.1.4.1.11150.3.4.0.1", "1.3.6.1.4.1.11.2.17.19.3.4.0.1", "1.3.6.1.4.1.11150.3.4.0"
}
function compare (a, b)
local aList, bList, Na, Nb = {}, {} for num in a:gmatch("%d+") do table.insert(aList, num) end for num in b:gmatch("%d+") do table.insert(bList, num) end for i = 1, math.max(#aList, #bList) do Na, Nb = tonumber(aList[i]) or 0, tonumber(bList[i]) or 0 if Na ~= Nb then return Na < Nb end end
end
table.sort(OIDs, compare) for _, oid in pairs(OIDs) do print(oid) end</lang>
- Output:
1.3.6.1.4.1.11.2.17.5.2.0.79 1.3.6.1.4.1.11.2.17.19.3.4.0.1 1.3.6.1.4.1.11.2.17.19.3.4.0.4 1.3.6.1.4.1.11.2.17.19.3.4.0.10 1.3.6.1.4.1.11150.3.4.0 1.3.6.1.4.1.11150.3.4.0.1
Perl
<lang perl>my @OIDs = qw(
1.3.6.1.4.1.11.2.17.19.3.4.0.10 1.3.6.1.4.1.11.2.17.5.2.0.79 1.3.6.1.4.1.11.2.17.19.3.4.0.4 1.3.6.1.4.1.11150.3.4.0.1 1.3.6.1.4.1.11.2.17.19.3.4.0.1 1.3.6.1.4.1.11150.3.4.0
);
my @sorted =
map { $_->[0] } sort { $a->[1] cmp $b->[1] } map { [$_, join , map { sprintf "%8d", $_ } split /\./, $_] } @OIDs;
print "$_\n" for @sorted;</lang>
- Output:
1.3.6.1.4.1.11.2.17.5.2.0.79 1.3.6.1.4.1.11.2.17.19.3.4.0.1 1.3.6.1.4.1.11.2.17.19.3.4.0.4 1.3.6.1.4.1.11.2.17.19.3.4.0.10 1.3.6.1.4.1.11150.3.4.0 1.3.6.1.4.1.11150.3.4.0.1
Alternately, you can sort them as "version strings", which is a Perl syntax allowing you to specify a character string in the source code with the characters' codes specified as a dot-delimited sequence of integers.
<lang perl>my @sorted =
map { $_->[0] } sort { $a->[1] cmp $b->[1] } map { [$_, eval "v$_"] } @OIDs;</lang>
Perl 6
The sort routine accepts a sort key callback as the first argument. Here we generate a list of integers as the sort key for each OID, which gets sorted lexicographically with numeric comparison by default.
<lang perl6>.say for sort *.comb(/\d+/)».Int, <
1.3.6.1.4.1.11.2.17.19.3.4.0.10 1.3.6.1.4.1.11.2.17.5.2.0.79 1.3.6.1.4.1.11.2.17.19.3.4.0.4 1.3.6.1.4.1.11150.3.4.0.1 1.3.6.1.4.1.11.2.17.19.3.4.0.1 1.3.6.1.4.1.11150.3.4.0
>;</lang>
- Output:
1.3.6.1.4.1.11.2.17.5.2.0.79 1.3.6.1.4.1.11.2.17.19.3.4.0.1 1.3.6.1.4.1.11.2.17.19.3.4.0.4 1.3.6.1.4.1.11.2.17.19.3.4.0.10 1.3.6.1.4.1.11150.3.4.0 1.3.6.1.4.1.11150.3.4.0.1
Alternatively, using the sprintf-based approach used by the Perl solution, for comparison (input elided):
<lang perl6>.say for sort *.split('.').fmt('%08d'), <...>;</lang>
Or if using a third-party module is acceptable:
<lang Perl6>use Sort::Naturally;
.say for sort &naturally, <...>;</lang>
Python
We need to split the input and map each part to int otherwise elements gets compared as a string <lang Python> data = [
'1.3.6.1.4.1.11.2.17.19.3.4.0.10', '1.3.6.1.4.1.11.2.17.5.2.0.79', '1.3.6.1.4.1.11.2.17.19.3.4.0.4', '1.3.6.1.4.1.11150.3.4.0.1', '1.3.6.1.4.1.11.2.17.19.3.4.0.1', '1.3.6.1.4.1.11150.3.4.0'
]
for s in sorted(data, key=lambda x: list(map(int, x.split('.')))):
print(s)
</lang>
Racket
<lang racket>#lang racket (require data/order)
- allows for key caching
(define (oid->oid-key o)
(map string->number (string-split o ".")))
(define oid-key< (order-<? datum-order))
(module+ test
(require rackunit) (check-equal? (sort '("1.3.6.1.4.1.11.2.17.19.3.4.0.10" "1.3.6.1.4.1.11.2.17.5.2.0.79" "1.3.6.1.4.1.11.2.17.19.3.4.0.4" "1.3.6.1.4.1.11150.3.4.0.1" "1.3.6.1.4.1.11.2.17.19.3.4.0.1" "1.3.6.1.4.1.11150.3.4.0") oid-key< #:key oid->oid-key #:cache-keys? #t) '("1.3.6.1.4.1.11.2.17.5.2.0.79" "1.3.6.1.4.1.11.2.17.19.3.4.0.1" "1.3.6.1.4.1.11.2.17.19.3.4.0.4" "1.3.6.1.4.1.11.2.17.19.3.4.0.10" "1.3.6.1.4.1.11150.3.4.0" "1.3.6.1.4.1.11150.3.4.0.1")))</lang>
Tests run with no output, indicating success.
REXX
This REXX version supports negative integers in the OID. <lang rexx>/*REXX program performs a sort of OID (Object IDentifiers ◄── used in Network data).*/
$= 1.3.6.1.4.1.11.2.17.19.3.4.0.10 , /* ◄──┐ */ 1.3.6.1.4.1.11.2.17.5.2.0.79 , /* ◄──┤ */ 1.3.6.1.4.1.11.2.17.19.3.4.0.4 , /* ◄──┼─◄─ six OID numbers (as a list).*/ 1.3.6.1.4.1.11150.3.4.0.1 , /* ◄──┤ */ 1.3.6.1.4.1.11.2.17.19.3.4.0.1 , /* ◄──┤ */ 1.3.6.1.4.1.11150.3.4.0 /* ◄──┘ */
- =words($) /*#: the number of OIDs in the $ list.*/
do i=1 for #; @.i=word($,i) /*build the @ array from each word in $*/ end /*i*/
L=length(#) /*length of the number of words in $.*/ call show 'before sort ───► ' /*display the @ array before sorting.*/
say copies('░', 79) /*display fence, separate before &after*/
call norma 1; call bSort #; call norma 0 /*expand/sort/shrink the internal OID's*/ call show ' after sort ───► ' /*display the @ array after sorting. */ exit /*stick a fork in it, we're all done. */ /*──────────────────────────────────────────────────────────────────────────────────────*/ bSort: procedure expose @.; parse arg n; m=n-1 /*N: is the number of @ array elements.*/
do m=m for m by -1 until ok; ok=1 /*keep sorting the @ array until done. */ do j=1 for m; _=j+1; if @.j>@._ then parse value @.j @._ 0 with @._ @.j ok end /*j*/ /* [↑] swap two out─of─order elements.*/ end /*m*/; return /* [↑] use a simple bubble sort. */
/*──────────────────────────────────────────────────────────────────────────────────────*/ norma: arg LZ; do j=1 for #; x=translate(@.j, , .); y= /*construct X version. */
do k=1 for words(x); _=word(x, k) /*get a number in X. */ if LZ then y=y right(_,30,0); else y=y _+0 /*add/elide leading 0's*/ end /*k*/ /*adjust number, append*/ @.j = translate( space(y), ., ' ') /*reconstitute number. */ end /*j*/ /*LZ: Leading Zero(es).*/ return /*── ─ ─ */
/*──────────────────────────────────────────────────────────────────────────────────────*/ show: do a=1 for #; say right("OID number",20) right(a,L) arg(1) @.a; end; return</lang>
- output when using the (internal) default input:
OID number 1 before sort ───► 1.3.6.1.4.1.11.2.17.19.3.4.0.10 OID number 2 before sort ───► 1.3.6.1.4.1.11.2.17.5.2.0.79 OID number 3 before sort ───► 1.3.6.1.4.1.11.2.17.19.3.4.0.4 OID number 4 before sort ───► 1.3.6.1.4.1.11150.3.4.0.1 OID number 5 before sort ───► 1.3.6.1.4.1.11.2.17.19.3.4.0.1 OID number 6 before sort ───► 1.3.6.1.4.1.11150.3.4.0 ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ OID number 1 after sort ───► 1.3.6.1.4.1.11.2.17.5.2.0.79 OID number 2 after sort ───► 1.3.6.1.4.1.11.2.17.19.3.4.0.1 OID number 3 after sort ───► 1.3.6.1.4.1.11.2.17.19.3.4.0.4 OID number 4 after sort ───► 1.3.6.1.4.1.11.2.17.19.3.4.0.10 OID number 5 after sort ───► 1.3.6.1.4.1.11150.3.4.0 OID number 6 after sort ───► 1.3.6.1.4.1.11150.3.4.0.1
Ring
<lang Ring>
/*
+-------------------------------------------------------------- + Program Name : SortOIDNumeric.ring + Date : 2016-07-14 + Author : Bert Mariani + Purpose : Sort OID List in Numeric Order +--------------------------------------------------------------
- /
oldOidList = [
".1.3.6.1.4.1.11150.3.4.0.21", ".1.3.6.1.4.1.11150.3.4.0.11", ".1.3.6.1.4.1.11150.3.4.0.2", ".1.3.6.1.4.1.11150.3.4.0.1", ".1.3.6.1.4.1.11.2.17.3773.0.2", ".1.3.6.1.4.1.11.2.17.3773.0.1", ".1.3.6.1.4.1.11.2.17.19.3.4.0.32", ".1.3.6.1.4.1.11.2.17.19.3.4.0.31", ".1.3.6.1.4.1.11.2.17.19.3.4.0.25", ".1.3.6.1.4.1.11.2.17.19.3.4.0.22", ".1.3.6.1.4.1.11.2.17.19.3.4.0.19", ".1.3.6.1.4.1.11.2.17.19.3.4.0.10", ".1.3.6.1.4.1.11.2.17.19.3.4.0.4" , ".1.3.6.1.4.1.11.2.17.19.3.4.0.3" , ".1.3.6.1.4.1.11.2.17.19.3.4.0.2" , ".1.3.6.1.4.1.11.2.17.19.3.4.0.1" , ".1.3.6.1.4.1.11.2.17.19.2.0.79", ".1.3.6.1.4.1.11.2.17.19.2.0.9" ]
### SHOW BEFORE SORT See nl + "oldOIDList Before Sort" +nl See oldOidList
#---------------------
delChar = "." nulChar = "" padChar = " " padSize = 6 newDotPadList = []
### Split list into lines for line in oldOidList
### Split line by . into components noDotList = str2list( substr(line, delChar, nl) )
### Pad components with left blanks to make equal size newPadList = PadStringList(noDotList, padChar, padSize)
### Join the components back to a line newDotPadString = JoinStringList(delChar, newPadList)
### Create new list - Alpha Add(newDotPadList, newDotPadString) next
### Sorts Alpha list newDotPadListSorted = sort(newDotPadList)
### SHOW ALPHA INTERMEDIATE OUTPUT See nl + "newDotPadListSorted Intermediate Sort" +nl See newDotPadListSorted
### Remove blanks for original look newOidList = RemovePadCharList( newDotPadListSorted, padChar, nulChar)
###--------------------
### SHOW AFTER SORT - NUMERIC See nl + "newOIDList Final Sort" +nl See newOidList
- --------------------------------------------------------------------
- Function: PadStringList
- newList = PadStringList(oldList, padChar, padSize )
- --------------------------------------------------------------------
Func PadStringList oldList, padChar, padSize
newList = [] for line in oldList newPadSize = padSize - len(line) newLine = Copy( padChar, newPadSize) + line Add(newList, newLine) next
### First line in all blank because of leading dot - remove Del(newList,1)
return newList
- ------------------------------------------------------------
- FUNC JoinStringList
- newString = JoinStringList( joinChar, oldList)
- ------------------------------------------------------------
Func JoinStringList joinChar, OldList
newString = "" for line in OldList newString = newString + joinChar + line next
return newString
- ---------------------------------------------------------------------
- FUNC RemovePadCharList
- newOidList = RemovePadCharList( oldList, padChar, nulChar)
- ---------------------------------------------------------------------
Func RemovePadCharList oldList, padChar, nulChar
newList = [] for line in oldList noPadString = substr(line, padChar, nulChar) Add(newList, noPadString) next
return newList
- -----------------------------------------------------------
>;</lang>
- Output:
.1.3.6.1.4.1.11.2.17.19.2.0.9 .1.3.6.1.4.1.11.2.17.19.2.0.79 .1.3.6.1.4.1.11.2.17.19.3.4.0.1 .1.3.6.1.4.1.11.2.17.19.3.4.0.2 .1.3.6.1.4.1.11.2.17.19.3.4.0.3 .1.3.6.1.4.1.11.2.17.19.3.4.0.4 .1.3.6.1.4.1.11.2.17.19.3.4.0.10 .1.3.6.1.4.1.11.2.17.19.3.4.0.19 .1.3.6.1.4.1.11.2.17.19.3.4.0.22 .1.3.6.1.4.1.11.2.17.19.3.4.0.25 .1.3.6.1.4.1.11.2.17.19.3.4.0.31 .1.3.6.1.4.1.11.2.17.19.3.4.0.32 .1.3.6.1.4.1.11.2.17.3773.0.1 .1.3.6.1.4.1.11.2.17.3773.0.2 .1.3.6.1.4.1.11150.3.4.0.1 .1.3.6.1.4.1.11150.3.4.0.2 .1.3.6.1.4.1.11150.3.4.0.11 .1.3.6.1.4.1.11150.3.4.0.21
Ruby
<lang ruby>%w[
1.3.6.1.4.1.11.2.17.19.3.4.0.10 1.3.6.1.4.1.11.2.17.5.2.0.79 1.3.6.1.4.1.11.2.17.19.3.4.0.4 1.3.6.1.4.1.11150.3.4.0.1 1.3.6.1.4.1.11.2.17.19.3.4.0.1 1.3.6.1.4.1.11150.3.4.0
] .sort_by{|oid| oid.split(".").map(&:to_i)} .each{|oid| puts oid}</lang>
- Output:
1.3.6.1.4.1.11.2.17.5.2.0.79 1.3.6.1.4.1.11.2.17.19.3.4.0.1 1.3.6.1.4.1.11.2.17.19.3.4.0.4 1.3.6.1.4.1.11.2.17.19.3.4.0.10 1.3.6.1.4.1.11150.3.4.0 1.3.6.1.4.1.11150.3.4.0.1
Sidef
<lang ruby>func sort_OIDs(ids) {
ids.sort_by { |id| id.split('.').map { Num(_) } }
}
var OIDs = %w(
1.3.6.1.4.1.11.2.17.19.3.4.0.10 1.3.6.1.4.1.11.2.17.5.2.0.79 1.3.6.1.4.1.11.2.17.19.3.4.0.4 1.3.6.1.4.1.11150.3.4.0.1 1.3.6.1.4.1.11.2.17.19.3.4.0.1 1.3.6.1.4.1.11150.3.4.0
)
sort_OIDs(OIDs).each { .say }</lang>
- Output:
1.3.6.1.4.1.11.2.17.5.2.0.79 1.3.6.1.4.1.11.2.17.19.3.4.0.1 1.3.6.1.4.1.11.2.17.19.3.4.0.4 1.3.6.1.4.1.11.2.17.19.3.4.0.10 1.3.6.1.4.1.11150.3.4.0 1.3.6.1.4.1.11150.3.4.0.1
Tcl
<lang Tcl>
- Example input data:
set oid_list [list \
1.3.6.1.4.1.11.2.17.19.3.4.0.10 \ 1.3.6.1.4.1.11.2.17.5.2.0.79 \ 1.3.6.1.4.1.11.2.17.19.3.4.0.4 \ 1.3.6.1.4.1.11150.3.4.0.1 \ 1.3.6.1.4.1.11.2.17.19.3.4.0.1 \ 1.3.6.1.4.1.11150.3.4.0 ]
set oid2_lists [list ] set dots_max 0 set i 0 foreach oid $oid_list {
set oid_list [split $oid "."] set dot_count [llength $oid_list] incr dot_count -1 if { $dot_count > $dots_max } { set dots_max $dot_count } set dots_arr(${i}) $dot_count lappend oid2_lists $oid_list incr i
}
- pad for strings of different dot counts
set oid3_lists [list] for {set ii 0} {$ii < $i} {incr ii} {
set oid_list [lindex $oid2_lists $ii] set add_fields [expr { $dots_max - $dots_arr(${ii}) } ] if { $add_fields > 0 } { for {set j 0} {$j < $add_fields} {incr j} { lappend oid_list -1 } } lappend oid3_lists $oid_list
} for {set n $dots_max} {$n >= 0 } {incr n -1} {
set oid3_lists [lsort -integer -index $n -increasing $oid3_lists]
}
- unpad strings of different dot counts
set oid4_lists [list] for {set ii 0} {$ii < $i} {incr ii} {
set oid_list [lindex $oid3_lists $ii] set j [lsearch -exact -integer $oid_list -1] if { $j > -1 } { set oid2_list [lrange $oid_list 0 ${j}-1] lappend oid4_lists $oid2_list } else { lappend oid4_lists $oid_list }
} foreach oid_list $oid4_lists {
puts [join $oid_list "."]
} </lang>
- Output:
% source sort-a-list-of-oids.tcl 1.3.6.1.4.1.11.2.17.5.2.0.79 1.3.6.1.4.1.11.2.17.19.3.4.0.1 1.3.6.1.4.1.11.2.17.19.3.4.0.4 1.3.6.1.4.1.11.2.17.19.3.4.0.10 1.3.6.1.4.1.11150.3.4.0 1.3.6.1.4.1.11150.3.4.0.1
zkl
Translation of http://rosettacode.org/wiki/Natural_sorting#zkl
Basically, blow apart each line into a list of numbers and sort that. <lang zkl>fcn sortOIDS(oids){ // oids is not modified, a new list is created
// pad each oid with a terminal (-1) so zip won't short cut oids=oids.pump(List(),fcn(oid){ (oid + ".-1").split(".").apply("toInt") }); oids.sort( // in place sort fcn(a,b){ // a & b are (x,y,z,...-1), eg (0,4,2,54,-1), (4,6,-1)
a.zip(b).reduce(fcn(_,[(a,b)]){ // if one list longer, zip truncates if(a==b) return(True); // continue to next field return(Void.Stop,a<b); // OIDa<OIDb == cmp this field },True);
}); oids.pump(List,fcn(list){ list[0,-1].concat(".") }) // back to strings
}</lang> <lang zkl>oids:=List(
"1.3.6.1.4.1.11.2.17.19.3.4.0.10", "1.3.6.1.4.1.11.2.17.5.2.0.79", "1.3.6.1.4.1.11.2.17.19.3.4.0.4", "1.3.6.1.4.1.11150.3.4.0.1", "1.3.6.1.4.1.11.2.17.19.3.4.0.1", "1.3.6.1.4.1.11150.3.4.0");
oids=sortOIDS(oids); oids.pump(Console.println); // print one OID per line</lang>
- Output:
1.3.6.1.4.1.11.2.17.5.2.0.79 1.3.6.1.4.1.11.2.17.19.3.4.0.1 1.3.6.1.4.1.11.2.17.19.3.4.0.4 1.3.6.1.4.1.11.2.17.19.3.4.0.10 1.3.6.1.4.1.11150.3.4.0 1.3.6.1.4.1.11150.3.4.0.1