views:

206

answers:

5

Hi - this question feels like it would have been asked already, but I've not found anything so here goes...

I have constructor which is handed a string which is delimited. From that string I need to populate an object's instance variables. I can easily split the string by the delimited to give me an array of strings. I know I can simply iterate through the array and set my instance variables using ifs or a switch/case statement based on the current array index - however that just feels a bit nasty. Pseudo code:

String[] tokens = <from generic string tokenizer>;

for (int i = 0;i < tokens.length;i++) {
   switch(i) {
      case(0): instanceVariableA = tokens[i];
      case(1): instanceVarliableB = tokens[i];
      ...
   }
}

Does anyone have any ideas of how I do this better/nicer?

For what it's worth, I'm working in Java, but I guess this is language independant.

+3  A: 

Uhm... "nasty" is in the way the constructor handles the parameters. If you can't change that then your code snippet is as good as it may be.

You could get rid of the for loop, though...

instanceVariableA = tokens[0];
instanceVariableB = tokens[1];

and then introduce constants (for readibilty):

instanceVariableA = tokens[VARIABLE_A_INDEX];
instanceVariableB = tokens[VARIABLE_B_INDEX];

NOTE: if you could change the string parameter syntax you could introduce a simple parser and, with a little bit of reflection, handle this thing in a slightly more elegant way:

String inputString = "instanceVariableA=some_stuff|instanceVariableB=some other stuff";
String[] tokens = inputString.split("|");
for (String token : tokens)
{
    String[] elements = token.split("=");
    String propertyName = tokens[0];
    String propertyValue = tokens[1];
    invokeSetter(this, propertyName, propertyValue); // TODO write method
}
Manrico Corazzi
I like this way, the for-each is much less cluttered...
Fraser
I've ended up going for the first part of this answer. It's conceptually very simple and avoids the clutter of a loop altogether. oh - and I can't change the input string easily. Thanks :o)
Tom Duckering
A: 

Could you not use a "for-each" loop to eliminate much of the clutter?

Fraser
A: 

I really think the way you are doing it is fine, and Manrico makes a good suggestion about using constants as well.

Another method would be to create a HashMap with integer keys and string values where the key is the index and the value is the name of the property. You could then use a simple loop and some reflection to set the properties. The reflection part might make this a bit slow, but in another language (say, PHP for example) this would be much cleaner.

Eric Petroelje
A: 

Python-specific solution:

Let's say params = ["instanceVariableA", "instanceVariableB"]. Then:

self.__dict__.update(dict(zip(params, tokens)))

should work; that's roughly equivalent to

for k,v in zip(params, tokens):
    setAttr(self, k, v)

depending on the presence/absence of accessors.

In a non-dynamic language, you could accomplish the same effect building a mapping from strings to references/accessors of some kind.

(Also beware that zip stops when either list runs out.)

jleedev
A: 

just an untested idea,

keep the original token...

String[] tokens = <from generic string tokenizer>;

then create

int instanceVariableA = 0;
int instanceVariableB = 1;

if you need to use it, then just

tokens[instanceVariableA];

hence no more loops, no more VARIABLE_A_INDEX...

maybe JSON might help?

zeroin23