4

中間点のリストを通過する点 A から点 B までのパスの長さを Python で計算しようとしています。私はそれを行う方法を知っていますが、reduce Built-in function を使用したいと思います

これまで試した理由は、完全に間違っていることに注意してください。これは次のとおりです。

reduce(lambda x,y: math.sqrt((y[1]-y[0])**2+(x[1]-x[0])**2) , ((1,2),(3,4),(1,8)))

何か案が?

ありがとう。

4

8 に答える 8

6

縮小する前にマッピングする必要があります。

points = [(1, 2), (3, 4), (1, 8)]
distances = (math.hypot(b[0]-a[0], b[1]-a[1])
             for a, b in zip(points, points[1:]))
total_distance = sum(distances)

または、使用する必要がある場合は、この目的には適してreduce()いますが:sum()

import operator

total_distance = reduce(operator.add, distances)

ポイントがたくさんある場合は、NumPy がこれを一度にすばやく行うのに役立つことがあります。

import numpy

total_distance = numpy.hypot(*numpy.diff(numpy.array(points), axis=0)).sum()

編集: math.hypot()NumPy メソッドを使用して追加します。

于 2011-11-17T16:28:21.230 に答える
4

きれいではありませんが、実行できます:-)

>>> tot = ((1,2),(3,4),(1,8))
>>> reduce(lambda d,((x0,y0),(x1,y1)): d + ((x1-x0)**2+(y1-y0)**2)**0.5, zip(tot[1:], tot[0:]), 0.0)
7.3005630797457695
于 2011-11-17T16:30:12.510 に答える
2

reduce()この目的には単に間違ったツールです。でそれを行うこと可能reduce()ですが、少し奇妙です:

def distance((x, d), y):
    return y, d + math.hypot(y[0] - x[0], y[1] - x[1])

print reduce(distance, [(3,4),(1,8)], ((1, 2), 0.0))[1]

版画

7.30056307975

呼び出しに渡される最後のパラメーターはreduce()、距離の開始点と初期値です。

于 2011-11-17T16:26:59.923 に答える
1

reduce はそのようには機能しません。初期値 a から開始します。これは、指定するか、イテラブルの最初の要素として取得されます。その後、提供された関数 (ラムダ) に a,next_element を渡し、結果を a, に格納し、すべての要素が繰り返されるまで繰り返します。

最初にあるポイントから次のポイントまでのすべての距離を計算し、次にそれらを合計することにより、sum と map で必要なことを行うことができます。

path = [(1,2),(3,4),(1,8)]
sum(map(lambda x,y: math.sqrt((x[0]-y[0])**2+(x[1]-y[1])**2), path[:-1],path[1:]))

編集: またはhypot関数 (thx @ralu) を使用:

sum(map(lambda x,y: math.hypot(x[0]-y[0],x[1]-y[1]), path[:-1],path[1:]))
于 2011-11-17T16:26:15.043 に答える
1

これは、あなたが書きたいようなコードではありません。Reduce は良い解決策ではありません。

反復的なものをお勧めします。これは、最も読みやすく、pythonic で保守可能なソリューションになります。

import math
path = [(1,2),(3,4),(1,8)]

def calc_dist(waypoints):
    dist = 0.0
    for i in range(len(waypoints) - 1):
        a = waypoints[i]
        b = waypoints[i+1]
        dist += math.hypot(a[0]-b[0], b[1]-a[1])
    return dist

print calc_dist( path )
于 2011-11-17T17:04:14.193 に答える
1

これはredux、ビルトインと組み合わせてreduce必要な結果を得ることができるメタイテレータです。この実装により、入力シーケンスのすべてのバッファリングが回避されます。

def redux(f):
  def execute(iterable):
    iterable = iter(iterable)
    try:
      state = iterable.next()
    except StopIteration:
      raise ValueError, 'empty sequences not supported'
    while True:
      newstate = iterable.next()
      yield f(state, newstate)
      state = newstate
  return execute

f = redux(lambda x, y: math.sqrt((y[0] - x[0])**2 + (y[1] - x[1])**2))
print reduce(operator.add, f(((1,2),(3,4),(1,8))))

上記の印刷物7.30056307975

関数は、関数の引数に必要な引数の数をカウントするためにredux使用することにより、スライディング ウィンドウで一度に 3 つ以上の引数をサポートするように一般化できます。inspect.getargspec

于 2011-11-17T16:50:33.640 に答える
0

私が提案しようとしていることは理想的ではないことを私は知っていますが、これは私の貢献のために得ることができる限り近いと思います。これは、reduceの最も伝統的なアプリケーションではない場合でも、解決するのが楽しい問題です。

重要な問題は、ポイント自体を上書きせずにポイントからポイントまでの距離を追跡することのようです。各ポイントに別の「寸法」を追加すると、走行距離を追跡できるフィールドが得られます。

iterable = ((1,2,0), (3,4,0), (1,8,0))
# originally ((1,2), (3,4), (1,8))

from math import sqrt

def func(tup1, tup2):
    '''function to pass to reduce'''

    # extract coordinates
    x0 = tup1[0]
    x1 = tup2[0]
    y0 = tup1[1]
    y1 = tup2[1]

    dist = tup1[2] # retrieve running total for distance

    dx = x1 - x0   # find change in x
    dy = y1 - y0   # find change in y

    # add new distance to running total
    dist += sqrt(dx**2 + dy**2) 

    # return 2nd point with the updated distance
    return tup2[:-1] + (dist,)  # e.g. (3, 4, 2.828)

今減らす:

reduce(func, iterable)[-1]
# returns 7.3005630797457695

このようにして、タプルの中間タプル(つまり、1つの「削減」の後)は次のようになります。

((3, 4, 2.8284271247461903), (1,8,0))
于 2011-11-17T17:55:10.787 に答える
0

楽しみのために、アプローチとは少し異なるアプローチの代替ソリューションを次に示しreduce(sum, map(hypot, zip(...)))ます。

tot = ((1,2),(3,4),(1,8))
reduce(lambda (d,(x,y)),b: (d+math.hypot(x-b[0],y-b[1]), b), tot, (0, tot[0]))[0]

reduceは実際にはタプル (距離、最後のポイント) を返すため、最後に があることに注意してください[0]。これはソリューションよりも効率的だと思いますzip、実際には確認していません。

于 2011-11-17T18:51:16.793 に答える