views:

1905

answers:

8

EDIT: Amazingly, newacct's answer has accumulated 12 points in the four hours since I posted my question. This, despite its being incorrect. As alternatives to php's associative array, newacct offers Java's HashMap and Python's dictionary, neither of which preserves key order.

cmcg provided a correct answer for the Java version. That is, to use a LinkedHashMap to preserve key order. Milhous suggested a TreeMap, but Piligrim pointed out that a TreeMap sorts elements by key, while LinkedHashMap preserves original order, which was the intent.

Alexander Ljungberg first indicated that an ordered dictionary was not currently available for Python. Daniel Pryden then provided a simple and straightforward alternative structure, a list of two-tuples.

In the hope that my beginner's Python syntax is correct,

# a list of two-tuples
stateList = [('ALABAMA', 'AL'), ('ALASKA', 'AK'), ('WISCONSIN', 'WI'), ('WYOMING', 'WY')]

for name, abbreviation in stateList:
    print name, abbreviation

Output:

ALABAMA AL
ALASKA AK
WISCONSIN WI
WYOMING WY

Which is exactly what was required.

Thanks to everyone who contributed. It's been educational.


In php one can handle a list of state names and their abbreviations with an associative array like this:

<?php
    $stateArray = array (
        "ALABAMA"=>"AL",
        "ALASKA"=>"AK",
        // etc...
        "WYOMING"=>"WY");

    foreach ($stateArray as $stateName => $stateAbbreviation)
    {
        print "The abbreviation for $stateName is $stateAbbreviation.\n\n";
    }
?>

Output ( * with key order preserved * ):

The abbreviation for ALABAMA is AL.

The abbreviation for ALASKA is AK.

The abbreviation for WYOMING is WY.

EDIT: Note that the order of array elements is preserved in the output of the php version. The Java implementation, using a HashMap, does not guarantee the order of elements. Nor, in fact, does the dictionary in Python.

How is this done in java and python? I only find approaches that supply the value, given the key, like python's:

stateDict = {
    "ALASKA" : "AK",
    "WYOMING" : "WY"
    }

for key in stateDict:
    value = stateDict[key]

Many thanks.

Lasoldo Solsifa

+14  A: 

in Python:

for key, value in stateDict.items(): # .iteritems() in Python 2.x
    print "The abbreviation for %s is %s." % (key, value)

in Java:

Map<String,String> stateDict;

for (Map.Entry<String,String> e : stateDict.entrySet())
    System.out.println("The abbreviation for " + e.getKey() + " is " + e.getValue() + ".");
newacct
Thank you very much for your help. Regarding the Java version, I take for granted that May.Entry is simply misspelled. It can be really confusing for a novice sorting out code when it has even a small typo in it. Is it safe to assume that stateDict is in fact a Map? A HashMap?
Lasoldo Solsifa
thanx, fixed. stateDict is a Map
newacct
I have edited my question to underscore that the order of array elements is preserved in the output of the php version. The Java implementation, using a Map, does not appear to guarantee the order of elements.
Lasoldo Solsifa
use a `LinkedHashMap` if you need to keep the order of the elements.
cd1
Thanks, CD1, for this suggestion. Meanwhile, the python version, using a dictionary, does not preserve order either. Any ideas? :)
Lasoldo Solsifa
Python dicts are, by definition, unordered. If you want ordered data in python, look at a list or other data structure.
nilamo
+2  A: 

in java for associative array use Map

import java.util.*;

class Foo
{
    public static void main(String[] args)
    {
     Map<String, String> stateMap = new HashMap<String, String>();
     stateMap.put("ALABAMA", "AL");
     stateMap.put("ALASKA", "AK");
     // ...
     stateMap.put("WYOMING", "WY");

     for (Map.Entry<String, String> state : stateMap.entrySet()) {
       System.out.printf(
       "The abbreviation for %s is %s%n",
       state.getKey(),
       state.getValue()
      );
     }
    }
}
o948
Thanks for the clear example! And it compiles and runs, does just what I expected. Your answer helped me sort out newacct's shorthand version. Frankly, without your code, I'd have been lost for quite a while.
Lasoldo Solsifa
Oops, noticed after the fact that the HashMap does not preserve order of elements. But a LinkedHashMap does!
Lasoldo Solsifa
+1  A: 

Another way of doing it in Java. Although a better way has already been posted, this one's syntactically closer to your php code.

for (String x:stateDict.keySet()){
  System.out.printf("The abbreviation for %s is %s\n",x,stateDict.get(x));
 }
MAK
This looks interesting, and it runs fine, but I admit it will take me a moment to sort it out! :) Thanks for the example.
Lasoldo Solsifa
+2  A: 

Also, to maintain insertion order, you can use a LinkedHashMap instead of a HashMap.

cmcg
Yep, a LinkedHashMap looks like exactly what I needed. Compiled, run, and the order is preserved. That's for the tip!
Lasoldo Solsifa
Your suggestion solved the Java version, can you recommend a replacement for the dictionary in acct's python version? It does not preserve order either...
Lasoldo Solsifa
+2  A: 

In python an ordered dictionary is available in Python 2.7 (not yet released) and Python 3.1. It's called OrderedDict.

Alexander Ljungberg
Thanks for the tip! I was beginning to think my question might go unanswered. I will admit that I am distressed, though, if it is true that php’s foreach($array as $key => $value) cannot be implemented in python. I'm afraid I don't understand why a dictionary of ordered keys must lose its order when retrieved. It's perplexing. Now I suppose I'm on the lookout for a work-around.
Lasoldo Solsifa
@Lasoldo Solsifa: when you say "a dictionary of ordered keys" do you mean an OrderedDict instance or a normal Python dict? Because a normal Python dict NEVER has ordered keys -- the spec says that the keys may be returned in any order. The difference is PHP actually uses an associative array, and Python uses a hashtable. They are similar but not exactly the same. In Python <= 2.6, using a list of 2-tuples is probably the better solution.
Daniel Pryden
Not knowing python, I knew first of its forthcoming ordered dictionary from Alexander Ljungberg's response to my question. I'm only looking for an associative array in general, from which I may retrieve my keys in the order they were inserted. I will look into your suggestion of a list of 2-tuples. Thanks for the help.
Lasoldo Solsifa
The standard dictionary is not ordered for performance reasons I imagine. The most common way to use a dictionary is not to go over it item by item but to look up individual items when needed. If all you want is to display the dictionaries in alphabetical order you can use "for key, value in (key, stateDict[key] for key in sorted(stateDict.keys()):"
Alexander Ljungberg
A: 

This is the modified code from o948 where you use a TreeMap instead of a HashMap. The Tree map will preserve the ordering of the keys by the key.

import java.util.*;

class Foo
{
 public static void main(String[] args)
 {
    Map<String, String> stateMap = new TreeMap<String, String>();
    stateMap.put("ALABAMA", "AL");
    stateMap.put("ALASKA", "AK");
    // ...
    stateMap.put("WYOMING", "WY");

    for (Map.Entry<String, String> state : stateMap.entrySet()) {
             System.out.printf(
                    "The abbreviation for %s is %s%n",
                    state.getKey(),
                    state.getValue()
            );
      }
    }
 }
Milhous
Thanks for the help. Answers to my question also indicated that a LinkedHashMap would preserve element order, so I did like you, only I substituted LinkedHashMap for the HashMap. Yours works too, so now I can choose between two solutions!
Lasoldo Solsifa
Oops. Pilgrim points out that TreeMap sorts elements by key, while LinkedHashMap preserves original order, which is what was required.
Lasoldo Solsifa
A: 

Along the lines of Alexander's answer...

The native python dictionary doesn't maintain ordering for maximum efficiency of its primary use: an unordered mapping of keys to values.

I can think of two workarounds:

  1. look at the source code of OrderedDict and include it in your own program.

  2. make a list that holds the keys in order:

    states = ['Alabamba', 'Alaska', ...]  
    statesd = {'Alabamba':'AL', 'Alaska':'AK', ...}
    for k in states:
        print "The abbreviation for %s is %s." % (k, statesd[k])
    
alberge
Daniel Pryden's suggestion of a list of two-tuples may be better.e.g. [('Alabamba', 'AL'), ('Alaska', 'AK'), ...]
alberge
A: 

TreeMap is not an answer to your question because it sorts elements by key, while LinkedHashMap preserves original order. However, TreeMap is more suitable for the dictionary because of sorting.

tulskiy
Thank you so much for pointing this out. Since my list of US states is, for the most part, in alphabetical order, I didn't notice that TreeMap was actually sorting the elements! I tested it, and sure enough, it did not preserve insertion order. Unlike LinkedHashMap, which remains the winner in this case.
Lasoldo Solsifa