programing

정수 목록에서 지정된 값에 가장 가까운 숫자를 가져옵니다.

randomtip 2023. 1. 25. 08:42
반응형

정수 목록에서 지정된 값에 가장 가까운 숫자를 가져옵니다.

정수 목록을 지정하면 입력에 입력한 숫자에 가장 가까운 숫자를 찾습니다.

>>> myList = [4, 1, 88, 44, 3]
>>> myNumber = 5
>>> takeClosest(myList, myNumber)
...
4

빨리 할 수 있는 방법이 없을까요?

목록이 정렬되었는지 확실하지 않은 경우 삽입 함수를 사용하여 지정된 수에서 최소 거리를 가진 요소를 찾을 수 있습니다.

>>> min(myList, key=lambda x:abs(x-myNumber))
4

dits에도 사용할 수 .{1: "a", 2: "b"}O(n)로 하다


목록이 이미 정렬되어 있거나 배열 정렬에 대한 대가를 한 번만 지불할 수 있는 경우 O(log n) 시간만 걸리는 @Lauritz의 답변에 나와 있는 이등분법을 사용합니다(단, 목록이 이미 정렬되어 있는지 확인하는 것은 O(n), 정렬은 O(n log n)입니다).

에는 기능 take_closestPEP8을 사용하다

' 쓰기'가 ''을 한다면, '빠른 쓰기'는 '빠른 실행'을 합니다.min매우 좁은 사용 사례를 제외하고는 선택 가능한 무기가 되어서는 안 됩니다.min솔루션은 목록의 모든 숫자를 검사하고 각 숫자에 대해 계산을 수행해야 합니다.대신 사용하는 것이 거의 항상 더 빠릅니다.

는 '거의'가 '거의'라는 한다.bisect_left를 사용하려면 목록을 정렬해야 합니다.목록을 한 번 정렬한 후 그대로 둘 수 있는 사용 사례가 있으면 좋겠습니다. 않은 경우에도 가 없으면 .take_closest , . . . . . . . .bisect을 사용하다의문스럽다면 두 가지 방법을 모두 시도해 보고 실제 차이를 살펴보십시오.

from bisect import bisect_left

def take_closest(myList, myNumber):
    """
    Assumes myList is sorted. Returns closest value to myNumber.

    If two numbers are equally close, return the smallest number.
    """
    pos = bisect_left(myList, myNumber)
    if pos == 0:
        return myList[0]
    if pos == len(myList):
        return myList[-1]
    before = myList[pos - 1]
    after = myList[pos]
    if after - myNumber < myNumber - before:
        return after
    else:
        return before

을 반감하고 이 반감하는지 것입니다.myNumber중간값을 보고 들어가야 합니다.즉, 가장 높은 투표 응답의 O(n) 실행 시간과 달리 실행 시간은 O(log n)입니다.만약 우리가 두 가지 방법을 비교하고 두 가지 방법을 모두 분류하여 제공한다면myList을 사용하다

$ python - m timeit - s "가장 가까운 Import take_module에서랜덤 Import randint에서a = 범위 1000, 1000, 10)" "take_take(a, randinttx1100, 1100)"
100000루프, 베스트 오브 3: 루프당 2.22usec
$ python - m timeit - s "가장 가까운 Import에서_min으로랜덤 Import randint에서a = 범위 1000, 1000, 10)" "with_min(a, randint 1100, 1100)"
10000루프, 베스트 오브 3: 루프당 43.9usec

그래서 이 특별한 테스트에서bisect거의 20배나 빨라요.목록이 길수록 차이가 커집니다.

만약 우리가 경쟁의 장을 평등하게 만든다면?myList정리가 필요한가?를 들어 매번 목록 복사본을 정렬한다고 가정해 봅시다. take_closest를 나가는 동안 호출됩니다.min수정되지 않은 솔루션위의 테스트의 200개 항목 목록을 사용하여bisect솔루션은 여전히 가장 빠르지만 약 30%밖에 되지 않습니다.

정렬 스텝이 O(n log(n)인 것을 고려하면 이상한 결과입니다!유일한 이유는min여전히 손해를 보고 있는 것은 정렬이 고도로 최적화된 C 코드로 이루어졌다는 것입니다.min모든 항목에 대해 람다 함수를 호출하여 터벅터벅 걸어가야 합니다.~하듯이myList크기가 커지면min결과적으로 해결 속도가 빨라집니다.주의: 우리는 모든 것을 그것에 유리하게 쌓아올려야 했습니다.min이기기 위한 해결책.

>>> takeClosest = lambda num,collection:min(collection,key=lambda x:abs(x-num))
>>> takeClosest(5,[4,1,88,44,3])
4

람다는 "익명" 함수(이름이 없는 함수)를 쓰는 특별한 방법입니다.람다는 표현식이므로 원하는 이름을 지정할 수 있습니다.

상기의 「긴」문법은, 다음과 같습니다.

def takeClosest(num,collection):
   return min(collection,key=lambda x:abs(x-num))
def closest(list, Number):
    aux = []
    for valor in list:
        aux.append(abs(Number-valor))

    return aux.index(min(aux))

이 코드는 목록에서 가장 가까운 번호의 색인을 제공합니다.

Kenny가 제시한 해결책TM은 전체적으로 가장 좋지만, 사용할 수 없는 경우(브라이튼 등)에는 이 기능으로 동작합니다.

목록을 반복하여 현재 가장 가까운 번호와 비교합니다.abs(currentNumber - myNumber):

def takeClosest(myList, myNumber):
    closest = myList[0]
    for i in range(1, len(myList)):
        if abs(i - myNumber) < closest:
            closest = i
    return closest
def find_nearest(array, value):
    array = np.asarray(array)
    idx = (np.abs(array - value)).argmin()
    return array[idx]

을 이용하여 그것을 실행하다

price_near_to=find_nearest(df['Close'], df['Close'][-2])

Lauritz의 이등분 사용 제안은 My List에서 My Number에 가장 가까운 값을 찾을 수 없습니다.대신 이등분할은 MyList에서 MyNumber 다음 순서로 다음 값을 찾습니다.따라서 OP의 경우 실제로는 4의 위치가 아닌 44의 위치가 반환됩니다.

>>> myList = [1, 3, 4, 44, 88] 
>>> myNumber = 5
>>> pos = (bisect_left(myList, myNumber))
>>> myList[pos]
...
44

5에 가장 가까운 값을 얻으려면 목록을 배열로 변환하고 numpy에서 argmin을 사용합니다.

>>> import numpy as np
>>> myNumber = 5   
>>> myList = [1, 3, 4, 44, 88] 
>>> myArray = np.array(myList)
>>> pos = (np.abs(myArray-myNumber)).argmin()
>>> myArray[pos]
...
4

이게 얼마나 빠를지 모르겠지만, 내 추측은 "별로"가 아닐 것이다.

구스타보 리마의 대답에 따라 확대됩니다.완전히 새로운 목록을 만들지 않고도 동일한 작업을 수행할 수 있습니다.목록의 값은 차분으로 대체할 수 있습니다.FOR루프가 진행됩니다.

def f_ClosestVal(v_List, v_Number):
"""Takes an unsorted LIST of INTs and RETURNS INDEX of value closest to an INT"""
for _index, i in enumerate(v_List):
    v_List[_index] = abs(v_Number - i)
return v_List.index(min(v_List))

myList = [1, 88, 44, 4, 4, -2, 3]
v_Num = 5
print(f_ClosestVal(myList, v_Num)) ## Gives "3," the index of the first "4" in the list.

@Lauritz의 대답에 덧붙이자면

실행 오류가 발생하지 않도록 하기 위해 다음 명령어 앞에 조건을 추가하는 것을 잊지 마십시오.bisect_left 표시:

if (myNumber > myList[-1] or myNumber < myList[0]):
    return False

따라서 전체 코드는 다음과 같습니다.

from bisect import bisect_left

def takeClosest(myList, myNumber):
    """
    Assumes myList is sorted. Returns closest value to myNumber.
    If two numbers are equally close, return the smallest number.
    If number is outside of min or max return False
    """
    if (myNumber > myList[-1] or myNumber < myList[0]):
        return False
    pos = bisect_left(myList, myNumber)
    if pos == 0:
            return myList[0]
    if pos == len(myList):
            return myList[-1]
    before = myList[pos - 1]
    after = myList[pos]
    if after - myNumber < myNumber - before:
       return after
    else:
       return before
def takeClosest(myList, myNumber):
    newlst = []
    for i in myList:
        newlst.append(i - myNumber)
    lstt = [abs(ele) for ele in newlst]
    print(myList[lstt.index(min(lstt))])

myList = [4, 1, 88, 44, 3]
myNumber = 5
takeClosest(myList,myNumber)

언급URL : https://stackoverflow.com/questions/12141150/from-list-of-integers-get-number-closest-to-a-given-value

반응형