# Distinct nearest pixels for floating-point coordinates

dem_rows and dem_cols contain float values for a number of things i can identify in an image, but I need to get the nearest pixel for each of them, and than to make sure I only get the unique points, and no duplicates.

The problem is that this code is ugly and as far as I get it, as unpythonic as it gets. If there would be a pure-numpy-solution (without for-loops) that would be even better.

# next part is to make sure that we get the rounding done correctly, and than to get the integer part out of it
# without the annoying floatingpoint-error, and without duplicates
fielddic={}
for i in range(len(dem_rows)):
# here comes the ugly part: abusing the fact that i overwrite dictionary keys if I get duplicates
fielddic[int(round(dem_rows[i]) + 0.1), int(round(dem_cols[i]) + 0.1)] = None
# also very ugly: to make two arrays of integers out of the first and second part of the keys
field_rows = numpy.zeros((len(fielddic.keys())), int)
field_cols = numpy.zeros((len(fielddic.keys())), int)
for i, (r, c) in enumerate(fielddic.keys()):
field_rows[i] = r
field_cols[i] = c


I'm not sure what you are doing, exactly, but looping over range(len(...)) is never very pythonic. Since you only use the index to look up values, you should just take the pairs using zip.

Also, that round() + 0.1 thing is unnecessary. Floats represent all integers in their accurate area exactly. If you are outside the accurate area (i.e. an exponent larger than the number of mantissa bits), that addition will not change the value of the float either. Thus, you can simply cast the result of round() to an integer.

If you need to take the unique items of something, the best way is to not use a dict, but a set.

int_rows = map(lambda x: int(round(x)), dem_rows)
int_cols = map(lambda x: int(round(x)), dem_cols)
s = set(zip(int_rows, int_cols))


Then iterate over the set, or unzip it into two sequences for constructing the arrays.

Note: In python 2.x map and zip create lists, so you may want to use itertools.izip and imap. In python 3.x they are fine as is.

• but i cant cast round() to an array, so i am still stuck with an ugly loop there- since dem_rows are floats and if i take the set of the zip, i just end up with the same thing, and i want to get rid of the for-loops) Commented Oct 25, 2013 at 9:35
• You can map the elements to ints, I'll update the answer.
– otus
Commented Oct 25, 2013 at 9:38
• and than how would it be best to iterate over the set or unzip and reconstruct? Commented Oct 25, 2013 at 9:48
• You can turn it back into two sequences using u_rows, u_cols = zip(*s). I'm not sure if you can pass those directly to numpy's array constructors or if you need to use tuple() first in python 3.x where zip returns iterators.
– otus
Commented Oct 25, 2013 at 9:54
• i am using 2.7 still Commented Oct 25, 2013 at 9:55

This is very unpythonic, however very common for Python newbies

 for i in range(len(something)):
do_someting_with(i)


You can iterate over items in the following way:

for item in something:
do_something_with(item)


or if you need also the index:

for idx, item in enumerate(something):
do_something_with(item)
do_something_with_idx(idx)


If you expect a list to comeout you can use list comperhansiom:

result = [ do_someting_with(item) for item in something ]


Or you can use some functional programming style:

result = map( do_someting_with, something )


Ok, i think i have found the best solution myself, with a little help from Otus, for the zip-set-unzip part, though i think my way of getting it to integers is more pythonic?

r1 = numpy.array(numpy.round(dem_rows), int)
c1 = numpy.array(numpy.round(dem_cols), int)
field_rows, field_cols = zip(*set(zip(r1, c1)))

• This solution was copied from Rev 1 of the question. If @usethedeathstar would repost this as a self-answer, then we can remove this post. Commented Nov 13, 2015 at 8:32