LINUX.ORG.RU

[python] любителям алгоритмов

 


0

0

Есть список, например такой:

#    0  1   2   3  4  5   6   7  8  9
a = [0, 0, 'A', 1, 0, 1, 'A', 1, 1, 0]
#               ^>>>>>>>>>^

Нужна функция, получающая индекс элемента (например 3), и выдающая индекс следующего за ним элемента, который равен 'A'. Причем, если передать в функцию '7' для этого примера, она должна вернуть индекс с начала списка, т.е. '2'. А если список не содержит элементов 'A', функция должна вернуть что-то осмысленное типа '0' или 'None', а не зацикливаться.

Использование функций вроде map и filter всячески приветствуется.

Вопрос #2 (pygtk): можно ли как-то применить метод (напр. hide()) к списку виджетов? Или только for для этого годится?


это в лоб одним циклом делается, в чем фокус?

wfrr ★★☆
()

// почти Java
int getNextWithA(char[] arr, int startIndex) {
    for (int i = 1; i <= arr.length; ++i) {
        int index = (startIndex + i) % arr.length;
        if (arr[index] == 'A') {
            return index;
        }
    }
    return null;
}

Legioner ★★★★★
()

Не особо думая:

def getNextElement(mylist, startpos, element):
    if element not in mylist or startpos > len(mylist)-1 or startpos < 0:
        return None
    for i in range(startpos, len(mylist)):
        if mylist[i] == element:
            return i
    for i in range(startpos):
        if mylist[i] == element:
            return i

anonymous
()

Вот те пытон-стайл.

~/test :) % cat test.py 
a = [0, 0, 'A', 1, 0, 1, 'A', 1, 1, 0]

def foo(l, s):
        def mod(i):
                return (i+s)%len(l)
        g = [mod(i) for i in range(len(l)) if l[mod(i)] == 'A']
        return g and g[0] or None

print foo(a, 7)
print foo(a, 3)
print foo([0,0], 1)
print foo([], 1)
~/test :) % python test.py 
2
6
None
None

Pi ★★★★★
()

def get_index(list, item, position=None):
    if item in list:
        return (list * 2).index(item, position) % len(list)

anonymous
()
Ответ на: комментарий от balodja

Понятное дело, что с обработкой IndexError выглядит совсем уж убого.

def myfunc(list,n,e):
  try: return filter(lambda t: t[1] == e, enumerate(list[n+1:]))[0][0]+n+1
  except IndexError: return None

balodja ★★★
()
Ответ на: комментарий от MATAH

Ух спасибо, народ. Стоило баиньки на ночь пойти, а вы уже столько методов придумали. Буду разбираться.

А с gtk-методами на списки виджетов как?

mosfet
() автор топика
Ответ на: комментарий от mosfet

Самым красивым и понятным оказалось решение 2го анонимуса с методом '.index' и умножением списка на два, за что ему отдельное спасибо.

mosfet
() автор топика
Ответ на: комментарий от tailgunner

> бгг.

А что не так? По-моему глобально и надежно.

mosfet
() автор топика
Ответ на: комментарий от mosfet

Умножать список нехорошо.

Посему можно оптимизировать:
def get_index(list, item, position=0):
    try: return ((list[position:] + list[:position]).index(item) + position) % len(list)
    except ValueError: return None

Или, в два поиска в один проход:
def get_index(list, item, position=0):
    try:
        return a.index(item, position)
    except ValueError:
        if position != 0:
            try:
                return a.index(item, 0, position)
            except ValueError:
                pass
    return None

anonymous
()
Ответ на: комментарий от anonymous

> Посему можно оптимизировать:

Преждевременная оптимизация - корень всех бед.

anonymous
()
Ответ на: комментарий от balodja

> Какая разница? Один фиг, это питон, там только ссылки в списке.

ну если например длина списка ~1e7 , то удвоение может оказаться затратной опреацией.

алсо если это не список, а некий объект эмулирующий список

anonymous
()
Ответ на: комментарий от mosfet

>>> умножением списка на два

>> бгг.

> А что не так? По-моему глобально и надежно.

Ты _на ровном месте_ вкрячил умножение списка, которое наверняка O(n), вместо % len(n), которое O(1).

> Удвоение списка сильно медленнее, чем два обрезания и склеивания?

Зачем в поставленной задаче вообще резать и склеивать списки? O_o

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

>Зачем в поставленной задаче вообще резать и склеивать списки? O_o

чтобы показать, насколько извращенно можно подойти к решению этой задачи на питоне.

anonymous
()
Ответ на: комментарий от tailgunner

> Зачем в поставленной задаче вообще резать и склеивать списки? O_o

чтобы минимизировать длину кода

anonymous
()
Ответ на: комментарий от tailgunner

>>>> умножением списка на два

>>> бгг.

>> А что не так? По-моему глобально и надежно.

> Ты _на ровном месте_ вкрячил умножение списка, которое наверняка O(n), вместо % len(n), которое O(1).

Насколько я понимаю, для красоты подобных решений существует itertools.

balodja ★★★
()

А теперь то же самое в обратную сторону. С методом index(). Пока очевидно только, что список нужно переворачивать.

mosfet
() автор топика
Ответ на: комментарий от balodja

> для красоты подобных решений существует itertools.

Каких "таких"? По условию задачи нам дан список, который по тем же условиям иногда надо сканировать 2 раза. В данном случае itertools не дадут ни красоты, ни оптимальности.

KISS.

tailgunner ★★★★★
()

Единственное вменяемое решение:

(defun next-idx (elt idx seq)
  (loop with len = (length seq) 
	for i from 1 do
	(setf idx (mod (incf idx) len)) 
	(cond ((equal elt (elt seq idx)) 
	           (return idx))
	      ((= i len) (return)))))

anonymous
()

def get_index(list, item, position=0):
    list_length = len(list)
    for i in xrange(position, position + list_length):
        index = i % list_length
        if list[index] == item:
            return index


>>> a = [0, 0, 'A', 1, 0, 1, 'A', 1, 1, 0]
>>> print get_index(a, 'A', 5)
6
>>> print get_index(a, 'A', 7)
2
>>> print get_index(a, 'B', 7)
None

anonymous
()
Ответ на: комментарий от anonymous

Ух ты, это питон такой? Что это за куча непонятных функций и скобочек?

balodja ★★★
()
Ответ на: комментарий от anonymous

Последний вариант, пожалуй, оптимален. Если нужно в крутить обратную сторону:

def get_index_back(list, item, position=0):
    list_length = len(list)
    for i in xrange(list_length + position, position, -1):
        index = i % list_length
        if list[index] == item:
            return index

>>> a = [0, 0, 'A', 1, 0, 1, 'A', 1, 1, 0]
>>> print get_index_back(a, 'A', 5)
2
>>> print get_index_back(a, 'A', 1)
6
>>> print get_index_back(a, 'B', 7)
None

mosfet
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.