I have this ugly code:
if ( v > 10 ) size = 6;
if ( v > 22 ) size = 5;
if ( v > 51 ) size = 4;
if ( v > 68 ) size = 3;
if ( v > 117 ) size = 2
Here is an object-oriented solution, a class called Mapper that maps values from any type that implements comparable to any target type.
Syntax:
Mapper mapper = Mapper.from("a","b","c").to(1,2,3);
// Map a single value
System.out.println(mapper.map("beef")); // 2
// Map a Collection of values
System.out.println(mapper.mapAll(
Arrays.asList("apples","beef","lobster"))); // [1, 2, 3]
Code:
public class Mapper, T> {
private final S[] source;
private final T[] target;
// Builder to enable from... to... syntax and
// to make Mapper immutable
public static class Builder> {
private final S2[] data;
private Builder(final S2[] data){
this.data = data;
}
public Mapper to(final T2... target){
return new Mapper(this.data, target);
}
}
private Mapper(final S[] source, final T[] target){
final S[] copy = Arrays.copyOf(source, source.length);
Arrays.sort(copy);
this.source = copy;
this.target = Arrays.copyOf(target, target.length);
}
// Factory method to get builder
public static , V> Builder from(final U... items){
return new Builder(items);
}
// Map a collection of items
public Collection mapAll(final Collection extends S> input){
final Collection output = new ArrayList(input.size());
for(final S s : input){
output.add(this.map(s));
}
return output;
}
// map a single item
public T map(final S input){
final int sourceOffset = Arrays.binarySearch(this.source, input);
return this.target[
Math.min(
this.target.length-1,
sourceOffset < 0 ? Math.abs(sourceOffset)-2:sourceOffset
)
];
}
}
Edit: finally replaced the map() method with a more efficient (and shorter) version. I know: a version that searches partitions would still be faster for large arrays, but sorry: I'm too lazy.
If you think this is too bloated, consider this:
Sure, all of these features could be easily removed, but the code would be less complete, less usable or less stable.