2

I have an object with large number of similar fields (like more than 10 of them) and I have to assign them values from an array of variable length. The solution would be either a huge nested bunch of ifs based on checking length of array each time and assigning each field

OR

a chain of ifs checking on whether the length is out of bounds and assigning each time after that check.

Both seem to be repetitive. Is there a better solution ?

Arun R
  • 8,372
  • 6
  • 37
  • 46

4 Answers4

4

If you language has switch/case with fallthrough, you could do it like this:

switch(array.length){
    case 15: field14 = array[14];
    case 14: field13 = array[13];
    case 13: field12 = array[12];
    // etc.
    case 1: field0 = array[0];
    case 0: break;
    default: throw Exception("array too long!");
}
Michael Borgwardt
  • 342,105
  • 78
  • 482
  • 720
  • if it is case 15, i need to assign all way from 15 to 0... and continue like that. – Arun R Mar 27 '10 at 17:20
  • @Icarus: due to the fallthrough in switch/case, the code above *will* assign all 15 fields when the array has a length of 15 – Michael Borgwardt Mar 27 '10 at 19:43
  • I was using c# and fall through does not work in it. I had to use case to make this happen. Also, had tried using var args but C# does not allow use of params with ref. – Arun R Mar 29 '10 at 10:33
1
for (int i = 0; i < fieldCount; i++)
    fields[i].value = array[i];

That is to say, maintain an array of fields that corresponds to your array of values.

Carl Manaster
  • 39,912
  • 17
  • 102
  • 155
  • I really don't think this answers the question. The whole point is that he's trying to apply these values to the fields *of a class/object*. Making all of the fields special types with their own `value` properties and making them indexable (and safe) is exactly the problem he's trying to solve, just redefined as something much more complicated. – Aaronaught Mar 27 '10 at 16:11
  • But if you've created the field array - through whatever means - then you can simply apply it, as I've done above. Versus solving that same problem at many points in the code. Do the work of making them indexable and safe once, then use the product to simplify the code. That's all I'm saying. – Carl Manaster Mar 27 '10 at 16:28
  • If you defined this as the creation of an indexer property, or some similar *specific* solution, I might agree. As it is, though, you're suggesting to solve the problem of mapping an array to fields by creating another array... which then has to be mapped to the exact same fields. – Aaronaught Mar 27 '10 at 16:36
  • The problem here is that I don't have the fields Array. – Arun R Mar 27 '10 at 17:18
1

If your language supports delegates, anonymous functions, that sort of thing, you can use those to clean it up. For example, in C# you could write this:

string[] values = GetValues();
SomeObject result = new SomeObject();
Apply(values, 0, v => result.ID = v);
Apply(values, 1, v => result.FirstName = v);
Apply(values, 2, v => result.LastName = v);
// etc.

The apply method would look like:

void Apply(string[] values, int index, Action<string> action)
{
    if (index < values.Length)
        action(values[index]);
}

This is obviously language-dependent, but something to think about regardless.


Another very simple option that we might be overlooking is, if you are actually trying to initialize an object from this value array (as opposed to update an existing object), to just accept the default values if the array isn't large enough.

C# example:

void CreateMyObject(object[] values)
{
    MyObject o = new MyObject();
    o.ID = GetValueOrDefault<int>(values, 0);
    o.FirstName = GetValueOrDefault<string>(values, 0);
    o.LastName = GetValueOrDefault<string>(values, 0);
    // etc.
}

void GetValueOrDefault<T>(object[] values, int index)
{
    if (index < values.Length)
        return (T)values[index];
    return default(T);
}

Sometimes the dumb solution is the smartest choice.

Aaronaught
  • 120,909
  • 25
  • 266
  • 342
  • That could be made cleaner by creating an array of delegates and looping through them. – Hosam Aly Mar 27 '10 at 16:16
  • @Hosam Aly: Not really, you're just going to have to write the same code I've already written to create the array. Unless you're doing this in more than one place, it doesn't save anything. – Aaronaught Mar 27 '10 at 16:18
  • It would at least save having to write the function invokation so many times, in addition to a variable for tracking indices. It would also be easier to update it if the object structure is updated, IMHO. – Hosam Aly Mar 27 '10 at 16:28
  • @Hosam Aly: Nothing is made easier unless this code is being used in several places, which the question does not state. If it's only done once, or once per class/array pair, then you end up writing *more* code just to initialize an unnecessary array. – Aaronaught Mar 27 '10 at 16:33
0

If your fields are declared in the same order of the array's elements, you could use reflection (if available in your language) to set these values. Here is an example of how you could do it in Java:

// obj is your object, values is the array of values
Field[] fields = obj.getClass().getFields();
for (int i = 0; i < fields.length && i < values.length; ++i) {
    fields[i].set(obj, values[i]);
}
Hosam Aly
  • 41,555
  • 36
  • 141
  • 182
  • This seems incredibly unlikely, and outright dangerous even if it's true. A simple refactoring of the class would break this and you wouldn't know it until runtime; you might not even get a runtime error, you'd just end up with corrupt data. You should never rely on the order of field declarations in a class. – Aaronaught Mar 27 '10 at 16:20
  • I agree that it's pretty dangerous, but if you come from a Python background then you might find it acceptable. Anyway, it's a tool that can be used for good or evil. – Hosam Aly Mar 27 '10 at 16:25
  • I didnt want to use this because of not being sure that reflection will give me the fields in same order as those declared in class. Is that always the case ? – Arun R Mar 27 '10 at 17:17
  • @Icarus: No, the documentation explicitly says that the order is not guaranteed. However, you could sort them in a predictable order. Check this other question for more information: http://stackoverflow.com/questions/1097807/java-reflection-is-the-order-of-class-fields-and-methods-standardized – Hosam Aly Mar 27 '10 at 18:57