Compare a list of strings: Difference between revisions
Walterpachl (talk | contribs) m (→{{header|REXX}}: terminate when no hope left) |
(→{{header|Java}}: added Java) |
||
Line 60: | Line 60: | ||
'''Notes''': <tt>asc</tt> indicates whether <tt>y</tt> is monotonically increasing, but not necessarily strictly monotonically increasing. |
'''Notes''': <tt>asc</tt> indicates whether <tt>y</tt> is monotonically increasing, but not necessarily strictly monotonically increasing. |
||
=={{header|Java}}== |
|||
{{works with|Java|8}} |
|||
<lang java>import java.util.Arrays; |
|||
public class CompareListOfStrings { |
|||
public static void main(String[] args) { |
|||
String[][] arr = {{"AA", "AA", "AA", "AA"}, {"AA", "ACB", "BB", "CC"}}; |
|||
for (String[] a : arr) { |
|||
System.out.printf("%s%n%s%n%s%n", Arrays.toString(a), |
|||
Arrays.stream(a).distinct().count() < a.length, |
|||
Arrays.equals(Arrays.stream(a).distinct().sorted().toArray(), a)); |
|||
} |
|||
} |
|||
}</lang> |
|||
Output: |
|||
<pre>[AA, AA, AA, AA] |
|||
true |
|||
false |
|||
[AA, ACB, BB, CC] |
|||
false |
|||
true</pre> |
|||
=={{header|ooRexx}}== |
=={{header|ooRexx}}== |
Revision as of 18:33, 30 June 2014
Given a list of arbitrarily many strings, show how to:
- test if they are all lexically equal
- test if every string is lexically less than the one after it (i.e. whether the list is in strict ascending order)
Each of those two tests should result in a single true of false value, which could be used as the condition of an if
statement or similar. If the input list has less than two elements, the tests should always return true.
There's no need to provide a complete program & output: Assume that the strings are already stored in an array/list/sequence/tuple variable (whatever is most idiomatic) with the name strings
, and just show the expressions for performing those two tests on it (plus of course any include's and custom functions etc. that it needs), with as little distractions as possible.
Try to write your solution in a way that does not modify the original list, but if it does then please add a note to make that clear to readers.
If you need further guidance/clarification, see #Perl and #Python for solutions that use implicit short-circuiting loops, and #Perl_6 for a solution that gets away with simply using a built-in language feature.
Related tasks:
C++
Assuming that the strings
variable is of type std::vector<std::string>
:
<lang cpp>#include <algorithm>
std::is_sorted(strings.begin(), strings.end(),
[](std::string a, std::string b){ return !(b == a); }) ) // All equal
std::is_sorted(strings.begin(), strings.end(),
[](std::string a, std::string b){ return !(b < a); }) ) // Strictly ascending</lang>
D
<lang d>void main() {
import std.stdio, std.algorithm, std.range, std.string;
foreach (const strings; ["AA AA AA AA", "AA ACB BB CC"].map!split) { strings.writeln; strings.zip(strings.dropOne).all!(ab => ab[0] == ab[1]).writeln; strings.zip(strings.dropOne).all!(ab => ab[0] < ab[1]).writeln; writeln; }
}</lang>
- Output:
["AA", "AA", "AA", "AA"] true false ["AA", "ACB", "BB", "CC"] false true
J
Solution (equality test):<lang j> allEq =: 1 = +/@~: NB. or 1 = #@:~. or -: 1&|. or }.-:}:</lang> Solution (order test):<lang j> asc =: /: -: i.@# NB. or -:&(/:~) etc.</lang> Notes: asc indicates whether y is monotonically increasing, but not necessarily strictly monotonically increasing.
Java
<lang java>import java.util.Arrays;
public class CompareListOfStrings {
public static void main(String[] args) { String[][] arr = {{"AA", "AA", "AA", "AA"}, {"AA", "ACB", "BB", "CC"}}; for (String[] a : arr) { System.out.printf("%s%n%s%n%s%n", Arrays.toString(a), Arrays.stream(a).distinct().count() < a.length, Arrays.equals(Arrays.stream(a).distinct().sorted().toArray(), a)); } }
}</lang>
Output:
[AA, AA, AA, AA] true false [AA, ACB, BB, CC] false true
ooRexx
<lang oorexx>/* REXX ---------------------------------------------------------------
- 28.06.2014 Walter Pachl
- --------------------------------------------------------------------*/
Call test 'ABC',.list~of('AA','BB','CC') Call test 'AAA',.list~of('AA','AA','AA') Call test 'ACB',.list~of('AA','CC','BB') Exit
test: Procedure Use Arg name,list all_equal=1 increasing=1 Do i=0 To list~items-2
i1=i+1 Select When list[i1]==list[i] Then increasing=0 When list[i1]<<list[i] Then Do all_equal=0 increasing=0 End When list[i1]>>list[i] Then all_equal=0 End End
Select
When all_equal Then Say 'List' name': all elements are equal' When increasing Then Say 'List' name': elements are in increasing order' Otherwise Say 'List' name': neither equal nor in increasing order' End
Return</lang> output
List ABC: elements are in increasing order List AAA: all elements are equal List ACB: neither equal nor in increasing order
Perl
<lang perl>use List::Util 1.33 qw(all);
all { $strings[0] eq $strings[$_] } 1..$#strings # All equal all { $strings[$_-1] lt $strings[$_] } 1..$#strings # Strictly ascending</lang>
Alternatively, if you can guarantee that the input strings don't contain null bytes, the equality test can be performed by a regex like this:
<lang perl>join("\0", @strings) =~ /^ ( [^\0]*+ ) (?: \0 $1 )* $/x # All equal</lang>
Perl 6
In Perl 6, putting square brackets around an infix operator turns it into a listop that effectively works as if the operator had been but in between all of the elements of the argument list (or in technical terms, it folds/reduces the list using that operator, while taking into account the operator's inherent associativity and identity value to Do What I Mean™):
<lang perl6>[eq] @strings # All equal [lt] @strings # Strictly ascending</lang>
Python
A useful pattern is that when you need some function of an item in a list with its next item over possibly all items in the list then f(a, nexta) for a, nexta in zip(alist, alist[1:])
works nicely. (Especially if an index is not needed elsewhere in the algorithm).
<lang python>all(a == b for a, b in zip(strings, strings[1:]) # All equal
all(a < b for a, b in zip(strings, strings[1:]) # Strictly ascending</lang>
REXX
<lang rexx>/* REXX ---------------------------------------------------------------
- 28.06.2014 Walter Pachl
- --------------------------------------------------------------------*/
Call mklist 'ABC','AA','BB','CC' Call test 'ABC' Call mklist 'AAA','AA','AA','AA' Call mklist 'ACB','AA','CC','BB' Call test 'AAA' Call test 'ACB' Exit
mklist:
list=arg(1) do i=1 by 1 To arg()-1 call value list'.'i,arg(i+1) End Call value list'.0',i-1 Return
test: Parse Arg list all_equal=1 increasing=1 Do i=1 To value(list'.0')-1 While all_equal | increasing
i1=i+1 Select When value(list'.i1')==value(list'.i') Then increasing=0 When value(list'.i1')<<value(list'.i') Then Do all_equal=0 increasing=0 End When value(list'.i1')>>value(list'.i') Then all_equal=0 End End
Select
When all_equal Then Say 'List' value(list)': all elements are equal' When increasing Then Say 'List' value(list)': elements are in increasing order' Otherwise Say 'List' value(list)': neither equal nor in increasing order' End
Return</lang> output
List ABC: elements are in increasing order List AAA: all elements are equal List ACB: neither equal nor in increasing order
Tcl
The command form of the eq
and <
operators (introduced in Tcl 8.5) handle arbitrarily many arguments and will check if they're all equal/ordered. Making the operators work with a list of values is just a matter of using the expansion syntax with them.
<lang tcl>tcl::mathop::eq {*}$strings; # All values string-equal
tcl::mathop::< {*}$strings; # All values in strict order</lang>