Как найти несколько минимальных значений питон

Уведомления

  • Начало
  • » Python для новичков
  • » Как выбрать несколько минимальных значений из списка?

#1 Март 5, 2013 17:19:54

Как выбрать несколько минимальных значений из списка?

К примеру, есть список

Как сделать, чтобы получить, например, 3 минимальных значения из этого списка?

Отредактировано nickmetal (Март 5, 2013 17:20:51)

Офлайн

  • Пожаловаться

#2 Март 5, 2013 18:23:01

Как выбрать несколько минимальных значений из списка?

In [1]: a=[33,12,2,3,2]
 
In [2]: sorted(a)[:3]
Out[2]: [2, 2, 3]

или

In [3]: import heapq
 
In [4]: heapq.nsmallest(3, a)
Out[4]: [2, 2, 3]

Отредактировано reclosedev (Март 5, 2013 18:23:26)

Офлайн

  • Пожаловаться

#3 Март 6, 2013 04:47:29

Как выбрать несколько минимальных значений из списка?

a=[33,12,2,3,2]
print sorted(list(set(a)))[:3]
>>> [2, 3, 12]

Офлайн

  • Пожаловаться

#4 Март 6, 2013 13:32:26

Как выбрать несколько минимальных значений из списка?

FishHook

>>> a = [33, 12, 2, 3, 2]
>>> print sorted(set(a))[:3]
[2, 3, 12]
>>>

лучше однопроходной алгоритм сделать, чтобы не сортировать список

Отредактировано py.user.next (Март 6, 2013 13:33:48)

Офлайн

  • Пожаловаться

#5 Март 6, 2013 13:37:16

Как выбрать несколько минимальных значений из списка?

У меня теперь вопрос. Зачем внутри функции sorted использовать set?
Спасибо за ответ…

Офлайн

  • Пожаловаться

#6 Март 6, 2013 13:42:57

Как выбрать несколько минимальных значений из списка?

4kpt
У меня теперь вопрос. Зачем внутри функции sorted использовать set?Спасибо за ответ…

ТСа понять можно двояко, он же не удосужился рассказать нам, понимается ли под “минимальным” уникальное значение или нет.

Офлайн

  • Пожаловаться

#7 Март 6, 2013 16:51:15

Как выбрать несколько минимальных значений из списка?

FishHook
….он же не удосужился рассказать нам…

Я?

Ну, даже если есть одинаковые минимальные значения- то годится. Хочу использовать в “дураке” когда сравнивают величину карт в колоде, чтобы узнать, чем ходить

Отредактировано nickmetal (Март 6, 2013 16:51:46)

Офлайн

  • Пожаловаться

#8 Март 7, 2013 00:15:24

Как выбрать несколько минимальных значений из списка?

4kpt
У меня теперь вопрос. Зачем внутри функции sorted использовать set?

чтобы одинаковые элементы не принимать за разные минимальные значения

FishHook
ТСа понять можно двояко, он же не удосужился рассказать нам, понимается ли под “минимальным” уникальное значение или нет.

логически можно вывести, используя метод от противного:
предположим, что автор имел в виду три любых минимальных значения (одинаковых или разных), тогда можно найти одно минимальное значение и вывести его три раза; тогда задача превращается в поиск минимального значения в списке
но автор написал про выбор нескольких минимальных значений в названии темы, а не про одно, следовательно, получаем противоречие

nickmetal
Ну, даже если есть одинаковые минимальные значения- то годится.

а как оно годится ? если ты их выбираешь, то как ты потом определишь, какой картой ходить ?

Отредактировано py.user.next (Март 7, 2013 00:22:11)

Офлайн

  • Пожаловаться

#9 Март 7, 2013 10:03:13

Как выбрать несколько минимальных значений из списка?

Да нет, вопрос был просто о минимальных 3-х значениях, и, по-умолчанию допускаются одинаковые значения, так что отсеивать их это имхо ваша личная инициатива. А в картах… Как можно например семерку бубей и семерку крести просто цифрой 7 идентефицировать, карты уникальны же, эти при сортировке должны лечь рядом просто, и set не поможет.

Офлайн

  • Пожаловаться

#10 Март 7, 2013 13:26:24

Как выбрать несколько минимальных значений из списка?

py.user.next
а как оно годится ? если ты их выбираешь, то как ты потом определишь, какой картой ходить ?

я назвал карты в списке так diamons_7, clovers_8,…
И вот есть рандомная колода(список) для игрока из 6 карт, срезом я узнаю масть, и срезом же узнаю величину. И вот для моей примитивной логики нужно узнать самые маленькие карты из колоды, даже если есть одинаковые величины ( козырь я учту потом), чтобы ими походить. Я тут пока не пытаюсь создать сильно умного ИИ, но чтобы и не особо тупой был Надеюсь, ситуацию раскрыл и всем спасибо за ответы и спасибо, кто еще напишет разного рода замечания. И вот когда осветил ситуацию поподробней, интересно было бы узнать, каким способом узнать минимальные карты?

Отредактировано nickmetal (Март 7, 2013 13:28:40)

Офлайн

  • Пожаловаться

  • Начало
  • » Python для новичков
  • » Как выбрать несколько минимальных значений из списка?

Еще одно решение с использованием – array.argpartition() из модуля Numpy (гораздо быстрее работает для больших списков):

import numpy as np

In [45]: a = np.random.randint(0, 100, size=10)

In [46]: a
Out[46]: array([ 8, 51, 63, 31, 21,  9, 28, 19, 70, 57])

In [47]: a.argpartition(2)[:2]
Out[47]: array([0, 5], dtype=int64)

дает такой же результат как и argsort()

In [48]: a.argsort()[:2]
Out[48]: array([0, 5], dtype=int64)

Сравнение производительности для массива из 1.000.000 элемтов:

In [32]: a = np.random.randint(0, 1000, size=10**6)

In [33]: lst = a.tolist()

In [34]: a.shape
Out[34]: (1000000,)

In [35]: len(lst)
Out[35]: 1000000

# Кирилл Малышев
In [51]: %timeit sorted(enumerate(lst), key=lambda x:x[1])[:2]
1.68 s ± 10.3 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

# Alban
In [49]: %timeit smallest(lst, 2)
860 ms ± 5.44 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

# jfs    
In [37]: %timeit nsmallest(2, range(len(lst)), key=lst.__getitem__)
212 ms ± 4.86 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

# avtomato    
In [38]: %timeit a.argsort()[:2]
193 ms ± 10.9 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

# Sergey Gornostaev
In [36]: %timeit map(lst.index, nsmallest(2, lst))
75.4 ms ± 2.35 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

# MaxU    
In [39]: %timeit a.argpartition(2)[:2]
10.8 ms ± 37.2 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

I’d like to add another, more general approach:
Here’s a recursive way of finding the i-th minimums of a given list of numbers

def find_i_minimums(numbers,i):
    minimum = float('inf')
    if i==0:
        return []
    less_than_i_minimums = find_i_minimums(numbers,i-1)
    for element in numbers:
        if element not in less_than_i_minimums and element < minimum:
            minimum = element
    return less_than_i_minimums + [minimum]

For example,

>>> find_i_minimums([0,7,4,5,21,2,6,1],3) # finding 3 minimial values for the given list
[0, 1, 2]

( And if you want only the i-th minimum number you’d extract the final value of the list )

The time-complexity of the above algorithm is bad though, it is O(N*i^2) ( Since the recursion depth is i , and at each recursive call we go over all values in ‘numbers’ list whose length is N and we check if the minimum element we’re searching for isn’t in a list of length i-1, thus the total complexity can be described by a geometric sum that will give the above mentioned complexity ).

Here’s a similar but alternative-implementation whose time-complexity is O(N*i) on average. It uses python’s built-in ‘set’ data-structure:

def find_i_minimums(numbers,i):
    minimum = float('inf')
    if i==0:
        return set()
    less_than_i_minimums = find_i_minimums(numbers,i-1)
    for element in numbers:
        if element not in less_than_i_minimums and element < minimum:
            minimum = element
    return less_than_i_minimums.union(set({minimum}))

If your ‘i’ is small, you can use the implementations above and then extract how many minimums you want ( or if you want the second minimum, then in your case run the code for i=2 and just extract the last element from the output data-structure ).
But if ‘i’ is for example greater than log(N) , I’d recommend sorting the list of numbers itself ( for example, using mergesort whose complexity is O(N*log(N)) at worst case ) and then taking the i-th element. Why so? because as stated, the run-time of the algorithm above is not great for larger values of ‘i’.

0 / 0 / 0

Регистрация: 02.04.2019

Сообщений: 14

1

Найти два наименьших(минимальных) элемента массива

26.05.2019, 20:54. Показов 21383. Ответов 5


Студворк — интернет-сервис помощи студентам

Друзья,

В одномерном массиве целых чисел, помогите определить два наименьших элемента?
Они могут быть как равными (оба наименьшие), так и отличаться.



0



iSmokeJC

Am I evil? Yes, I am!

Эксперт PythonЭксперт Java

15825 / 8958 / 2597

Регистрация: 21.10.2017

Сообщений: 20,651

26.05.2019, 21:01

2

Лучший ответ Сообщение было отмечено ZhansultanM как решение

Решение

Python
1
2
3
4
5
from random import randint
 
a = [randint(1, 100) for i in range(20)]
print(*a)
print(*sorted(a)[:2])



1



ZhansultanM

0 / 0 / 0

Регистрация: 02.04.2019

Сообщений: 14

26.05.2019, 21:15

 [ТС]

3

Я разобрал что значит (*a), распишите пожалуйста что значит

Python
1
print(*sorted(a)[:2])
Python
1
2
3
4
5
6
7
8
from random import randint
 
a = []         
for i in range (20):    
    a.append (randint (1, 100)) 
print (a) 
 
print(*sorted(a)[:2])

Добавлено через 1 минуту
Хотя, понял кажется, вы отсортировали, а затем взяли 2 первых числа. Крутяк, спасибо



0



628 / 468 / 179

Регистрация: 28.05.2012

Сообщений: 1,399

27.05.2019, 05:18

4

Цитата
Сообщение от ZhansultanM
Посмотреть сообщение

что значит (*a)

Это распаковка



0



0 / 0 / 0

Регистрация: 12.01.2016

Сообщений: 13

23.12.2020, 13:22

5

Как найти 2 наименьших элемента, не через массив?
Например, если вводится последовательность целых чисел.



0



Catstail

Модератор

Эксперт функциональных языков программированияЭксперт Python

35204 / 19420 / 4064

Регистрация: 12.02.2012

Сообщений: 32,445

Записей в блоге: 13

23.12.2020, 13:50

6

iSmokeJC, а если в массиве 10 млн элементов? Не странно ли сортировать 10 млн ради двух макcимумов?

Добавлено через 4 минуты

Python
1
2
3
4
5
6
7
8
9
10
def two_max(arr):
    m1,m2=arr[0],None
    for a in arr[1:]:
        if a>m1:
            m1,m2=a,m1
        elif m2==None or a>m2:
            m2=a
    return (m1,m2)
    
print(two_max([1,9,-4,2,6,7,3]))



1



Функция действительно может быть изменена, чтобы найти вторую наименьшую:

def second_smallest(numbers):
    m1, m2 = float('inf'), float('inf')
    for x in numbers:
        if x <= m1:
            m1, m2 = x, m1
        elif x < m2:
            m2 = x
    return m2

Старая версия основывалась на деталях реализации Python 2, которые None всегда сортируются перед чем-либо еще (поэтому он тестируется как “меньше” ); Я заменил это с помощью float('inf') как дозорного, так как бесконечность всегда проверяется как больше любого другого числа. В идеале исходная функция должна была использовать float('-inf') вместо None там, чтобы не привязываться к деталям реализации, другие реализации Python могут не делиться.

Демо:

>>> def second_smallest(numbers):
...     m1, m2 = float('inf'), float('inf')
...     for x in numbers:
...         if x <= m1:
...             m1, m2 = x, m1
...         elif x < m2:
...             m2 = x
...     return m2
... 
>>> print second_smallest([1, 2, 3, 4])
2

Вне функции, которую вы обнаружили, почти так же эффективно использовать функцию heapq.nsmallest(), чтобы вернуть два наименьших значения из iterable, и из этих двух выбрать второе (или последнее) значение:

from heapq import nsmallest

def second_smallest(numbers):
    return nsmallest(2, numbers)[-1]

Как и вышеприведенная реализация, это решение O (N); сохраняя вариант кучи, каждый шаг принимает время logK, но K является константой здесь (2)! Что бы вы ни делали, не используйте сортировку; который принимает время O (NlogN).

Добавить комментарий