Hi,I have a Map, actually a TreeMap, which will automatically sort the keys alphabetically. The keys are Strings, like "VARIABLE" + i, e.g: VARIABLE0, VARIABLE1, VARIABLE2, etc.If the total number of entries < 10, then the sorted order is ok:VARIABLE0VARIABLE1VARIABLE2But, if the total number of entries > 10, the sorted order is not what I want:VARIABLE0VARIABLE1VARIABLE10VARIABLE11VARIABLE12...VARIABLE2VARIABLE20VARIABLE21...VARIABLE3VARIABLE30VARIABLE31...I want the order be:VARIABLE0VARIABLE1VARIABLE2...VARIABLE9VARIABLE10VARIABLE11....Can you help me to achieve this? Thank you very much.
|
|
0
|
|
|
|
Reply
|
www
|
11/20/2007 5:43:20 PM |
|
www wrote:> Hi,> > I have a Map, actually a TreeMap, which will automatically sort the keys > alphabetically. The keys are Strings, like "VARIABLE" + i, e.g: ....> I want the order be:> VARIABLE0> VARIABLE1> VARIABLE2> ..> VARIABLE9> VARIABLE10> VARIABLE11> ...> > Can you help me to achieve this? Thank you very much.> > Write a class, possibly an anonymous inner class, that implementsComparator<String> and whose compare method returns the order you want.Pass an instance of your Comparator to the appropriate TreeMap constructor.An alternative approach would be to wrap your TreeMap in a Map class youwrite. On insertion, change the key to remove the "VARIABLE" part of thestring, and convert the remainder to an Integer. The order you want isthe natural sort order for Integer. When returning keys as results,concatenate with "VARIABLE" to recover the original key.Patricia
|
|
0
|
|
|
|
Reply
|
Patricia
|
11/20/2007 6:49:12 PM
|
|
www <www@nospam.com> wrote:> Hi,>> I have a Map, actually a TreeMap, which will automatically sort the keys> alphabetically. The keys are Strings, like "VARIABLE" + i, e.g:> VARIABLE0, VARIABLE1, VARIABLE2, etc.>> If the total number of entries < 10, then the sorted order is ok:>> VARIABLE0> VARIABLE1> VARIABLE2>> But, if the total number of entries > 10, the sorted order is not what I> want:>> VARIABLE0> VARIABLE1> VARIABLE10> VARIABLE11> VARIABLE12> ..> VARIABLE2> VARIABLE20> VARIABLE21> ..> VARIABLE3> VARIABLE30> VARIABLE31> ..>> I want the order be:> VARIABLE0> VARIABLE1> VARIABLE2> ..> VARIABLE9> VARIABLE10> VARIABLE11> ...>> Can you help me to achieve this? Thank you very much.I don't know of any simple Java built in function to help you. You have towrite some code to do that.You have a few options on how to do that.You can write your own Comparator object which implements the Comparefunction for Strings, and then write the code yourself to compare twostrings so that X10 comes after X2 instead of before it. When you createyour TreeMap you pass your Comparator object in the constructor so it willuse your logic for sorting the entries.I wrote one of these back in the 70's (in C of course not Java) to make theUnix ls command sort file names the way you want your strings to sort. Itbroke the names into logical sets of letters and numbers, and then sortedthe letter substrings using normal dictionary sort and sorted the numbersubstrings using numeric sort.The other option to change the sort order is to create a new object for thekeys instead of using strings. If every one of your keys follows thespecific format you mention above (name + number), this approach can workwell. Create the key object which keeps the name and number as separateinstance variables. Create a toString() method which produces the stringversion of the key. Create a compare method that does the type of compareof two of these objects like you want. That is, compare the strings, andif they are equal, compare the numbers.Oh, what the hey, here's the code for the custom key solution:import java.util.Map;import java.util.TreeMap;import java.util.Random;public class SortKey{ public static void main(String args[]) { Map<MyKey,Integer> m = new TreeMap<MyKey,Integer>(); Random rand = new Random(); m.put(new MyKey("A", 1), rand.nextInt(99)); m.put(new MyKey("A", 10), rand.nextInt(99)); m.put(new MyKey("B", 1), rand.nextInt(99)); m.put(new MyKey("B", 10), rand.nextInt(99)); m.put(new MyKey("B", 2), rand.nextInt(99)); m.put(new MyKey("B", 20), rand.nextInt(99)); m.put(new MyKey("B", 3), rand.nextInt(99)); m.put(new MyKey("B", 30), rand.nextInt(99)); System.out.println("Map is: " + m); }}class MyKey implements Comparable<MyKey>{ String var; int num; MyKey(String v, int n) { var = v; num = n; } public String getVar() { return var; } public int getNum() { return num; } public String toString() { return String.format("%s%d", var, num); } public int compareTo(MyKey k) { int r = getVar().compareTo(k.getVar()); if (r == 0) return ((Integer)getNum()).compareTo(k.getNum()); return r; }}Which produces the output:Map is: {A1=82, A10=86, B1=86, B2=24, B3=7, B10=18, B20=81, B30=86}-- Curt Welch http://CurtWelch.Com/curt@kcwc.com http://NewsReader.Com/
|
|
0
|
|
|
|
Reply
|
curt
|
11/20/2007 6:51:16 PM
|
|
On Nov 21, 2:43 am, www <w...@nospam.com> wrote:> Hi,>> I have a Map, actually a TreeMap, which will automatically sort the keys> alphabetically. The keys are Strings, like "VARIABLE" + i, e.g:> VARIABLE0, VARIABLE1, VARIABLE2, etc.>> If the total number of entries < 10, then the sorted order is ok:>> VARIABLE0> VARIABLE1> VARIABLE2>> But, if the total number of entries > 10, the sorted order is not what I> want:>> VARIABLE0> VARIABLE1> VARIABLE10> VARIABLE11> VARIABLE12> ..> VARIABLE2> VARIABLE20> VARIABLE21> ..> VARIABLE3> VARIABLE30> VARIABLE31> ..>> I want the order be:> VARIABLE0> VARIABLE1> VARIABLE2> ..> VARIABLE9> VARIABLE10> VARIABLE11> ...>> Can you help me to achieve this? Thank you very much.A possible way is to make each string value end with a double-digitfigure ; VARIABLE8 => VARIABLE08( or VARIABLE008 ).Another one is to implement java.util.Comparator specific to yourvalue strings and create TreeMap instance with it.I think the first way is easier :)
|
|
0
|
|
|
|
Reply
|
ynseo
|
11/20/2007 6:52:25 PM
|
|
"www" <www@nospam.com> wrote in message news:fhv6bs$iqm$1@news.nems.noaa.gov...> Hi,>> I have a Map, actually a TreeMap, which will automatically sort the keys > alphabetically. The keys are Strings, like "VARIABLE" + i, e.g: VARIABLE0, > VARIABLE1, VARIABLE2, etc.>> If the total number of entries < 10, then the sorted order is ok:>> VARIABLE0> VARIABLE1> VARIABLE2>>> But, if the total number of entries > 10, the sorted order is not what I > want:>> VARIABLE0> VARIABLE1> VARIABLE10> VARIABLE11> VARIABLE12Yes, this is this natural order for strings. You might try to change the keys to be more nicely formatted (e.g. VARIABLE0001 vs. VARIABLE1). Alternatively, you could replace the string with a more meaningful object, as in class VariableId extends Comparable <VariableId> { String name; int id public boolean equals (Object o1) { // override equals to return true when both match } public int hashcode () { // compute hashcode based on name and id } public int compareTo (VariableId x) { // Compare it to itself--you set the natural order } }But if you can't do those you can always supply the TreeMap with a custom Comparator that sets the sort order.new Comparator () <String> { public int compare (String s1, String s2) { // Parse the two strings to separate the variable from the suffix digits // compare the string portions. If not zero, answer that // otherwise compare the numeric portions. If not zero answer that // otherwise nswer zero--they're the same }}This comparator is inefficient, however, because it parses both keys all over again on every comparison. I haven't validated this code--it's just to explain the concepts.Matt Humphrey http://www.iviz.com/
|
|
0
|
|
|
|
Reply
|
Matt
|
11/20/2007 7:01:10 PM
|
|
www wrote:> Hi,> > I have a Map, actually a TreeMap, which will automatically sort the keys > alphabetically. The keys are Strings, like "VARIABLE" + i, e.g: > VARIABLE0, VARIABLE1, VARIABLE2, etc.> > If the total number of entries < 10, then the sorted order is ok:> > VARIABLE0> VARIABLE1> VARIABLE2> > > But, if the total number of entries > 10, the sorted order is not what I > want:> > VARIABLE0> VARIABLE1> VARIABLE10> VARIABLE11> VARIABLE12> ...> VARIABLE2> VARIABLE20> VARIABLE21> ...> VARIABLE3> VARIABLE30> VARIABLE31> ...> > I want the order be:> VARIABLE0> VARIABLE1> VARIABLE2> ...> VARIABLE9> VARIABLE10> VARIABLE11> ....> > Can you help me to achieve this? Thank you very much.> > I suggest not using a map of Strings in this case:SortedMap<Integer, Something>;Or, using a ListList<Something>If you absolutely must using Strings, then tell me this:Which order would these strings be in? A1B10, B2A9Regardless of your answer there, you'll need to write a Comparator<String> implementation that will give the correct ordering.Hope this helps,Daniel.-- Daniel Pitts' Tech Blog: <http://virtualinfinity.net/wordpress/>
|
|
0
|
|
|
|
Reply
|
Daniel
|
11/20/2007 7:05:21 PM
|
|
www <www@nospam.com> wrote:> Hi,>> I have a Map, actually a TreeMap, which will automatically sort the keys> alphabetically. The keys are Strings, like "VARIABLE" + i, e.g:> VARIABLE0, VARIABLE1, VARIABLE2, etc.>> If the total number of entries < 10, then the sorted order is ok:>> VARIABLE0> VARIABLE1> VARIABLE2>> But, if the total number of entries > 10, the sorted order is not what I> want:>> VARIABLE0> VARIABLE1> VARIABLE10> VARIABLE11> VARIABLE12> ..> VARIABLE2> VARIABLE20> VARIABLE21> ..> VARIABLE3> VARIABLE30> VARIABLE31> ..>> I want the order be:> VARIABLE0> VARIABLE1> VARIABLE2> ..> VARIABLE9> VARIABLE10> VARIABLE11> ...>> Can you help me to achieve this? Thank you very much.Thanks for exercise. Here's some code I wrote as examples of how to do it.import java.util.Map;import java.util.TreeMap;import java.util.Random;import java.util.Comparator;import java.util.Arrays;public class SortKey{ public static void main(String args[]) { comparatorSolution(); } static void comparatorSolution() { Map<String,Integer> m = new TreeMap<String,Integer>(new VarNameSorter()); Random rand = new Random(); m.put("", rand.nextInt(99)); m.put("1", rand.nextInt(99)); m.put("2", rand.nextInt(99)); m.put("10", rand.nextInt(99)); m.put("20", rand.nextInt(99)); m.put("A", rand.nextInt(99)); m.put("B", rand.nextInt(99)); m.put("A1", rand.nextInt(99)); m.put("A10", rand.nextInt(99)); m.put("A2", rand.nextInt(99)); m.put("A20", rand.nextInt(99)); m.put("A1.1", rand.nextInt(99)); m.put("A1.2", rand.nextInt(99)); m.put("A1.10", rand.nextInt(99)); m.put("A1X", rand.nextInt(99)); m.put("A1Y", rand.nextInt(99)); System.out.println("Map is:"); for (String var : m.keySet()) System.out.printf("\"%s\"=%d\n", var, m.get(var)); } static void myKeySolution() { Map<MyKey,Integer> m = new TreeMap<MyKey,Integer>(); Random rand = new Random(); m.put(new MyKey("A", 1), rand.nextInt(99)); m.put(new MyKey("A", 10), rand.nextInt(99)); m.put(new MyKey("B", 1), rand.nextInt(99)); m.put(new MyKey("B", 10), rand.nextInt(99)); m.put(new MyKey("B", 2), rand.nextInt(99)); m.put(new MyKey("B", 20), rand.nextInt(99)); m.put(new MyKey("B", 3), rand.nextInt(99)); m.put(new MyKey("B", 30), rand.nextInt(99)); System.out.println("Map is: " + m); }}class MyKey implements Comparable<MyKey>{ String var; int num; MyKey(String v, int n) { var = v; num = n; } public String getVar() { return var; } public int getNum() { return num; } public String toString() { return String.format("%s%d", var, num); } public int compareTo(MyKey k) { int r = getVar().compareTo(k.getVar()); if (r == 0) return ((Integer)getNum()).compareTo(k.getNum()); return r; }}/** * Sort variable names with mixed strings and numbers. * * Curt Welch <curt@kcwc.com> * 11-20-2007 */class VarNameSorter implements Comparator<String>{ public int compare(String v1, String v2) { // Split var names into digit and non digit substrings String[] v1a = splitVarName(v1); String[] v2a = splitVarName(v2); for (int i = 0; i < v1a.length; i++) { if (i >= v2a.length) return +1; // v2 is shorter - it comes first int r = compareChunk(v1a[i], v2a[i]); if (r != 0) return r; } if (v1a.length < v2a.length) return -1; // v1 is shorter - it comes first return 0; // they are the same } // split into digit and non digit substrings private String[] splitVarName(String name) { String[] a = new String[0]; for (int i = 0; i < name.length();) { int start = i; boolean isDigit = Character.isDigit(name.charAt(i)); while (i < name.length() && (isDigit == Character.isDigit(name.charAt(i)))) i++; a = Arrays.copyOf(a, a.length + 1); a[a.length-1] = name.substring(start, i); } return a; } // compare digits strings by int value, other strings by natural order. private int compareChunk(String s1, String s2) { if (isNum(s1) && isNum(s2)) return valueOf(s1) - valueOf(s2); return s1.compareTo(s2); } // Is the first character a digit? private boolean isNum(String s) { return s.length() > 0 && Character.isDigit(s.charAt(0)); } private int valueOf(String s) { try { return Integer.parseInt(s); } catch (NumberFormatException e) {} return 0; }}-- Curt Welch http://CurtWelch.Com/curt@kcwc.com http://NewsReader.Com/
|
|
0
|
|
|
|
Reply
|
curt
|
11/20/2007 8:25:08 PM
|
|
www <www@nospam.com> writes:> I have a Map, actually a TreeMap, which will automatically sort the> keys alphabetically. True.> The keys are Strings, like "VARIABLE" + i, e.g:> VARIABLE0, VARIABLE1, VARIABLE2, etc.....> But, if the total number of entries > 10, the sorted order is not what> I want:>> VARIABLE0> VARIABLE1> VARIABLE10> VARIABLE11> VARIABLE12> ..> VARIABLE2> VARIABLE20....> I want the order be:> VARIABLE0> VARIABLE1> VARIABLE2> ..> VARIABLE9> VARIABLE10> VARIABLE11> ...As you said, the default order of comparison on strings is lexical, sothat is what you get.You need to make a different comparison, and provide it to the TreeSetas a Comparator.Try, e.g., public static class VariableComparator implements Comparator<String> { public int compare(String a, String b) { int res = a.length() - b.length(); if (res == 0) { res = a.substring(8).compareTo(b.substring(8)); } return res; } }It assumes that the strings do in fact start with "VARIABLE" and arefollowed by the number. > Can you help me to achieve this? Thank you very much.You might want to reconsider the approach. All you seem to need is aset of numbers. You can always prefix with "VARIABLE" later. A BitSet would perhaps suffice./L-- Lasse Reichstein Nielsen - lrn@hotpop.com DHTML Death Colors: <URL:http://www.infimum.dk/HTML/rasterTriangleDOM.html> 'Faith without judgement merely degrades the spirit divine.'
|
|
0
|
|
|
|
Reply
|
Lasse
|
11/20/2007 9:13:07 PM
|
|
Lasse Reichstein Nielsen <lrn@hotpop.com> writes:
> www <www@nospam.com> writes:
>
>> I have a Map, actually a TreeMap, which will automatically sort the
>> keys alphabetically.
......long snip.....
> You might want to reconsider the approach. All you seem to need is a
> set of numbers. You can always prefix with "VARIABLE" later.
> A BitSet would perhaps suffice.
Uhm, no. It was a Map, not a Set. Forget the last part.
/L
--
Lasse Reichstein Nielsen - lrn@hotpop.com
DHTML Death Colors: <URL:http://www.infimum.dk/HTML/rasterTriangleDOM.html>
'Faith without judgement merely degrades the spirit divine.'
|
|
0
|
|
|
|
Reply
|
Lasse
|
11/20/2007 9:19:33 PM
|
|
On Tue, 20 Nov 2007 12:43:20 -0500, www <www@nospam.com> wrote, quoted
or indirectly quoted someone who said :
>
>Can you help me to achieve this? Thank you very much.
You need to write a Comparable or Comparator. See
http://mindprod.com/jgloss/comparator.html
http://mindprod.com/jgloss/comparable.html
http://mindprod.com/jgloss/sort.html
There is one that will do what you want, but it perhaps overly
complicated part of http://mindprod.com/products1.html#INI
Roughly you must either split the field on every compare or spit it
when you construct the object and compare on the text part and if you
get a tie compare on the numeric part.
--
Roedy Green Canadian Mind Products
The Java Glossary
http://mindprod.com
|
|
0
|
|
|
|
Reply
|
Roedy
|
11/21/2007 1:23:47 AM
|
|
|
9 Replies
63 Views
(page loaded in 0.322 seconds)
Similiar Articles: std::map< MyString, MyString > comparison operator? - comp.lang ...So the question is, what does <string> implement that <MyString> needs in order to work as a Key in a std::map? Thanks in advance for your help. inserting class objects into maps - comp.lang.c++.moderated ...I know this is a simple question, so any help would be very much appreciated. How do i insert a class into my map object along with a string as a key... Finding an int key less than or equal to - comp.lang.c++.moderated ...>From the wording of your question I am unclear as to exactly what you intend by a "map of int." A map is formed using key/value ... operator()(const typename std::map<Key ... shared_ptr as map key - comp.lang.c++.moderatedCan shared_ptr be used as map key. It has operator< defined, but what make me doubt ... Post Question | Groups | ... remote terminal : function keys do not work - comp.unix.solaris ...... Post Question | Groups | ... Is there a way to map keys somehow? (I am using bash, but can use ksh as well) thanks! rectangular edge detection - comp.soft-sys.matlabhii all, I am working in matlab for a sorting system. ... Post Question | Groups ... built on detected line segments in image edge map to ... Join two files with join keys in reverse sort order on AIX - comp ...Sorting a quarter-billion records (three times!) is not to be ... reverse sort order on AIX programming.itags.org: Unix & Linux question: Join two files with join keys ... 11.x: Changing keyboard layout - comp.sys.hp.hpuxI want to change a key from . to , and there is no setting in the serial 700/70 terminal. ... Question - Printing 2-up on 11x17 - comp.graphics ... Navigate table rows using arrow keys - comp.lang.javascript ...... asked if they could use the arrow keys ... number for arbitrarily sorting the rows in a table. ... Does the primary key value ... Contacts DB Question - comp.databases ... Encoding question - comp.lang.perl.misc... g=sub{print@_};sub r($$\$){my($w,$x,$y)=@_;for(keys%$x ... Ben -- perl -e'print map {/.(.)/s} sort unpack "a2 ... Encoding question - comp.lang.perl.misc Hi, I have a text ... c++ - Map keys sorting - Stack OverflowI'm building object-system for my application. Now I have such code: std::map<std::string, Object*> mObjects; The idea is to update each object of class Object (call ... collections - How to sort a Map on the values in Java ...@user157196 solution is good but I thing doing this is against the Map contract. Maps are supposed to use keys to store and retrieve values and sorting a map by value ... 7/8/2012 9:14:16 PM
|