2

Others have asked similar questions, but the answers haven't helped me. I'm a beginner working through a tutorial and struggling with this last step.

I have a list of neighbors and have created a function (called distance_all()) that, for a given neighbor, will return a list containing how far away each of the other neighbors are from the given neighbor. Now I'm trying to write a function that orders the list from nearest to furthest neighbor, and I can't get it to work. I also need the function to take an optional third argument that specifies how many neighbors are returned.

Here's the original list of neighbors:

neighbors = [{'name': 'Fred', 'avenue': 4, 'street': 8},
 {'name': 'Suzie', 'avenue': 1, 'street': 11},
 {'name': 'Bob', 'avenue': 5, 'street': 8},
 {'name': 'Edgar', 'avenue': 6, 'street': 13},
 {'name': 'Steven', 'avenue': 3, 'street': 6},
 {'name': 'Natalie', 'avenue': 5, 'street': 4}]

When I run the function that calculates distance, I get the following:

#input
distance_all(fred, neighbors)

#output
[{'name': 'Suzie', 'avenue': 1, 'street': 11, 'distance': 4.242640687119285},
 {'name': 'Bob', 'avenue': 5, 'street': 8, 'distance': 1.0},
 {'name': 'Edgar', 'avenue': 6, 'street': 13, 'distance': 5.385164807134504},
 {'name': 'Steven', 'avenue': 3, 'street': 6, 'distance': 2.23606797749979},
 {'name': 'Natalie', 'avenue': 5, 'street': 4, 'distance': 4.123105625617661}]

Now I'm trying to write a function that (1) runs the distance_all() function, (2) orders the output list from nearest to furthest, and (3) has an optional third argument that specifies how many neighbors to include in the output list. I haven't gotten to this third step yet because I'm struggling with the second, but any help is appreciated. I've tried a number of things, but here is my most recent attempt:

def nearest_neighbors(first_neighbor, neighbors, number = None):
    neighbor_distance = [distance_all(first_neighbor, neighbors)]
    return (sorted(neighbor_distance, key = lambda i: i['distance']))

When I run nearest_neighbors(fred, neighbors, 2) I get the error TypeError: list indices must be integers or slices, not str. I don't know what I'm doing wrong. Thanks for your help.

dwpage
  • 79
  • 4
  • 1
    `neighbor_distance = [distance_all(first_neighbor, neighbors)]` makes it a list of list of dict. I suppose `neighbor_distance = distance_all(first_neighbor, neighbors)` is what you meant. – 9000 Jul 25 '19 at 14:13
  • how do you calculate the distance? – user8426627 Jul 25 '19 at 14:13
  • Ah dang, that must have been causing the index issue. It works now that I removed the extra list brackets. Thanks! I'm using pythagorean theorem encoded in a function to calculate the distance with street numbers being x-values and avenue numbers being y-values. – dwpage Jul 25 '19 at 14:34

2 Answers2

4

Use list slicing

Ex:

def nearest_neighbors(first_neighbor, neighbors, number = None):
    neighbor_distance = distance_all(first_neighbor, neighbors)    #remove [] 
    return sorted(neighbor_distance, key = lambda i: i['distance'])[:number]

Demo:

neighbor_distance = [{'name': 'Suzie', 'avenue': 1, 'street': 11, 'distance': 4.242640687119285},
 {'name': 'Bob', 'avenue': 5, 'street': 8, 'distance': 1.0},
 {'name': 'Edgar', 'avenue': 6, 'street': 13, 'distance': 5.385164807134504},
 {'name': 'Steven', 'avenue': 3, 'street': 6, 'distance': 2.23606797749979},
 {'name': 'Natalie', 'avenue': 5, 'street': 4, 'distance': 4.123105625617661}]

number = 3
print(sorted(neighbor_distance, key = lambda i: i['distance'])[:number])

Output:

[{'avenue': 5, 'distance': 1.0, 'name': 'Bob', 'street': 8},
 {'avenue': 3, 'distance': 2.23606797749979, 'name': 'Steven', 'street': 6},
 {'avenue': 5, 'distance': 4.123105625617661, 'name': 'Natalie', 'street': 4}]
Rakesh
  • 81,458
  • 17
  • 76
  • 113
  • That works! Do you mind explaining how the addition of ```[:number]``` works, and why I was getting the error? Thanks for your help. – dwpage Jul 25 '19 at 14:15
  • I am using list slicing. https://stackoverflow.com/questions/509211/understanding-slice-notation – Rakesh Jul 25 '19 at 14:17
  • Nice. That makes sense. I still don't understand why I was getting the error, so any help in that regard is appreciated. – dwpage Jul 25 '19 at 14:27
1

your error is because of the list in neighbor_distance, neighbor_distance = distance_all(first_neighbor, neighbors) instead of neighbor_distance = [distance_all(first_neighbor, neighbors)] will not throw the error. Of course, this change alone will not solve your overall problem and list slicing as noted in answer above is the best way to solve it.

jatayu
  • 11
  • 3