>

주문 장에서 다음과 같은 목록으로 값을받습니다 :

list1 = [...,'ethbtc', '0.077666', '10', '0.077680', '15',...]
------------------------ ^ symbol ----- ^ value ----- ^ quantity--

이 목록에는 약 100 개의 기호가 있으며 각 기호마다 40 개의 값이 있습니다. 항상 같은 순서입니다.
잔액의 100 %를 지불하면이 시점에서 시스템이 구매하는 최대 가격을 확인하고 싶습니다.

따라서 0.077666에서 11 ETH를 구매하려는 경우 실제 가격은 0.077680이됩니다. 첫 번째 가격에는 10 개의 ETH 만 있기 때문입니다.
평균을 얻고 싶지 않습니다. 그 순간은 그 정도가 될 것입니다

내 코드에는 중첩 된 for 루프가 있고 2 개의 목록을 반복합니다 :

<올>
  • coinlist =이 symbollist = [ethbtc, eoseth,...] 와 같이 100 개의 기호가 모두 나열됩니다    
  • a 라는 인덱스 목록  값과 수량이 항상 같은 지점에 있기 때문에
    와이즈 비즈   

    내 코드 :

    a = ['1', '3', '5', ...]
    
    

    이 코드의 기능 :
    1) 심볼리스트의 모든 심볼을 반복합니다.
    2) 발견 된 모든 심볼에 대해 사용 가능한 수량을 찾습니다.
    3) 잔액 (예 : 10 ETH)이 qty보다 작은 경우 루프가 중단됩니다.
    4) 충분하지 않을 때까지 합계 목록에서 모든 수량을 계속 검색하고 요약하지 않으면

    코드는 의도 한대로 작동하지만 그렇게 빠르지는 않습니다. 예상대로 for symbolnow in symbollist: sumlist = [] for i in a: quantity = float(list1[list1.index(symbolnow) + (i+1)] if symbolnow in list1 else 0) sumlist.append(quantity) if sum(sumlist) > mycurrentbalance: maxvalue = float(list1[list1.index(symbolnow) + i] if symbolnow in list1 else -1) break else: maxvalue = -1  실행하는 데 시간이 오래 걸립니다.

    질문
    더 빠른 코드 작동 방식 이 시나리오 나 정규 표현식에서 목록 이해력이 더 좋습니까? 내 코드가 매우 추악합니까?

    미리 감사합니다!

    수정 :
    입력과 원하는 출력을 명확히하려면 샘플 :

    list1.index
    와이즈 비즈  <-잔액은 ETH입니다.
    list1 = [...,'ethbtc', '0.077666', '1', '0.077680', '1.5', '0.077710', '3', '0.078200', '4',...] 의 세 번째 항목마다  ETH의 수량이므로 목록에서 mycurrentbalance = 5.5 입니다.

    따라서 모든 ETH (이 경우 5.5)를 판매하려는 경우 최대 값은 '0.077710'입니다

    list1   ['1', '1.5', '3', '4'] 전후 100 기호 포함  다른 값의 수량과 기호가 있습니다

    list1
    • 답변 # 1

      user3080953의 답변 외에도 데이터가 더 효율적일뿐만 아니라 복잡성을 처리하는 데 도움이되기 때문에 데이터를 사전 처리해야합니다. 여기서는 목록을 디코딩하고 데이터를 사용하는 두 가지 작업을 한 번에 수행합니다. 먼저 해독 한 다음 사용하십시오.

      제 생각에 목표 형식은 다음과 같아야합니다 :

      prices_and_quantities_by_symbol = {
          'ethbtc': {
              'prices':[0.077666, 0.077680, 0.077710, 0.078200], 
              'quantities':[1, 1.5, 3, 4]
          }, 
          'btceth': {
              ...
          }, 
      ...}
      
      

      이제해야 할 일 :

      for symbol, prices_and_quantities in prices_and_quantities_by_symbol.items(): # O(len(symbol_list))
          total = 0
          for p, q in zip(prices_and_quantities["prices"], prices_and_quantities["quantities"]): # O(len(quantities))
              total += q # the running sum
              if total >= my_current_balance:
                  yield symbol, p # this will yield the symbol and the associated max_value
                  break
      
      

      대상 형식으로 데이터를 얻는 방법? 목록을 반복하고 기호를 찾으면 다음 기호까지 값과 수량을 저장하기 시작하십시오.

      prices_and_quantities_by_symbol = {}
      symbol_set = (symbol_list) # O(len(symbol_list))
      for i, v in enumerate(list1): # O(len(list1))
          if v in symbol_set:  # amortized O(1) lookup
              current_prices = []
              current_quantities = []
              current_start = i+1
              prices_and_quantities_by_symbol[v] = {
                  'prices':current_prices, 
                  'quantities':current_quantities
              }
          else: # a value or a quantity
              (current_prices if (i-current_start)%2==0 else current_quantities).append(float(v))
      
      

      특히 수량/값 목록이 길면 약간 최적화되지만 흥미로운 최적화 방법이 있습니다. 수량이 아닌 누적 수량을 저장하지 마십시오.

      prices_and_running_total_by_symbol = {
          'ethbtc': {
              'prices':[0.077666, 0.077680, 0.077710, 0.078200], 
              'running_total':[1, 2.5, 5.5, 9.5]
          }, 
          'btceth': {
              ...
          }, 
      ...}
      
      

      이제 bisect 를 사용하여 max_value를 매우 빠르게 찾을 수 있습니다. . bisect.bisect_left(rts, my_current_balance) 이후 코드를 이해하기 쉽게되었습니다.  첫 번째 누적 합계 >= my_current_balance 의 인덱스를 반환합니다 :

      for symbol, prices_and_running_totals in prices_and_running_totals_by_symbol.items(): # O(len(symbol_list))
          ps = prices_and_running_totals["prices"]
          rts = prices_and_running_totals["running_total"]
          i = bisect.bisect_left(rts, my_current_balance) # O(log(len(rts)))
          yield symbol, ps[i] # this will yield the symbol and the associated max_value
      
      

      총계를 쌓으려면 가격과 수량을 다르게 처리해야합니다.

      # O(len(list1))
      ...
      if v in symbol_set:  # amortized O(1) lookup*
          ...
      elif (i-current_start)%2==0:
          current_prices.append(float(v))
      else:
          current_running_totals.append((current_running_totals[-1] if current_running_totals else 0.0) + float(v))
      
      

      모든 것을 함수 (또는 더 나은 클래스의 메소드)에 넣으십시오 :

      prices_and_running_totals_by_symbol = process_data(list1)
      for symbol, max_value in symbols_max_values(prices_and_running_totals_by_symbol, my_current_balance):
          print(symbol, max_value)
      
      

      문제를 두 부분으로 나누면 (디코딩 및 사용) 어떻게 코드가 더 빨라지고 이해가 쉬워 지는지 알 수 있습니다.

    • 답변 # 2

      전처리 list1  그것을 dict에 저장하십시오. 이것은 당신이 list1 를 반복한다는 것을 의미합니다.  내부 루프가 실행될 때마다 한 번.

      price_dict = {'ethbtc': ['0.077666', '10', '0.077680', '15'], 'btceth': [...], ...}
      
      

      a 를 반복하는 대신 , range 를 반복  (파이썬 3) 또는 xrange  (파이썬 2). 이것은리스트 대신 이터레이터를 사용하고 코드를 더 유연하게 만듭니다.

      range(0, len(price_dict[symbol]), 2)
      
      

    • 답변 # 3

      귀하의 경우 고정 간격이 있으면 슬라이스 객체를 사용하면 'a'루프에 도움이 될 것이라고 생각합니다. 아래와 같이 목록 슬라이스를 객체에 저장할 수 있습니다 (1 또는 2 개의 다른 팁). 해당 입력 데이터를 사전 처리 할 기회가 있다면 실제로해야한다는 점에 대해서는 위의 사용자에 동의합니다. 팬더 라이브러리를 사용하는 것이 좋습니다. 매우 빠르기 때문에 사전도 값을 해싱 ​​할 수 있습니다.

      input_data = ['ethbtc', '0.0776666', '10', '0.077680', '15']  # Give your variables meaningful names
      length = 20 # a variable to store how long a list of values is for a particular symbol.
      for symbol in symbollist: # Use meaningful names if loops too
          start = input_data.index(symbol)  # break up longer lines
          # Some exception handling here
          indxs = slice(start: start+length:2) # python lets you create slice objects
          quantities = [float(number) for number in input_data[indxs]]
          if sum(quantities) > mycurrentbalance:
              # Whatever code here
              ....
      
      

    관련 자료

  • 이전 c# - net 앱에서 DateTimeNow 차단
  • 다음 java - '사용자 추가'버튼을 클릭하는 방법은 무엇입니까?