Я немного поработал над этой проблемой и просто чувствую себя полностью потерянным. Похоже, это было бы очень фундаментально, но, похоже, не могло его решить. Я на самом деле не ищу точного ответа, скорее, если я на правильном пути. Я только что закончил свою 3-ей неделю введения в программирование, поэтому я уверен, что некоторые форматирования немного завораживают, поэтому извините.
Я пытаюсь определить функцию, которая может принимать два списка: list1
и list2
и посмотреть, будет ли list1
служить подписок для list2
а также учитывать порядок.
Например, в книге вопрос гласит:
Если list1
определяется как: [15, 1, 100]
и list2
определяется как: [20, 15, 30, 50, 1, 100]
то list1
является подсписком list2
потому что числа в list1
(15, 1 и 100) отображаются в list2
в том же порядке.
Однако list [15, 50, 20]
не является списком list2
потому что порядок не совпадает.
Я не уверен, что я пойду правильно, но я хотел бы добавить то, что у меня есть до сих пор, и хотел бы, чтобы на него было высказано мнение. Я добавил комментарии, чтобы дать немного больше информации о моем мыслительном процессе.
l1 = eval(input('\nPlease enter a list of integers: '))
l2 = eval(input('\nPlease enter a second list of integers: '))
def subList(l1, l2):
'Takes two lists as input from the user and determines'
'True if list1 is a sublist of list2 and false otherwise.'
newLst = []
indexNum = 0
result = subList(l1, l2)
if len(l1) > len(l2):
return False
elif l1 == []:
return True
for num in l1:
#My thinking here is that this while loop should run for as long as ther variable indexNum
#Doesn't exceed the length of lst2, allowing me to compare every num of lst1 with that of lst2
while indexNum < len(l2):
#If I come across a number in lst2, at a certain index, that the same as lst1 I want
#to execute the following:
if l2[indexNum] == num:
#I've added a blank list at the top, newLst, which I want to append the matching number to.
newLst.append(l2[indexNum])
#I'll also want to still add one to the indexNum variable to compare the next number in lst2
indexNum = indexNum + 1
break
#If the number at lst2[indexNum] isn't equal to that of lst1, I still want to add to the
##indexNum variable to keep going through the loop and comparing the other items.
else:
indexNum = indexNum + 1
## I'm thinking here that if at the end of the outer loop, if my newLst is equal to the lst1, then that
## should mean that it works as a sub list. I could be wrong here and my thinking is way off though.
## If it is equal then the return value should be true, if not false.
if l1 == newLst:
return True
else:
return False
return True
Я пошел и проверил ваш код. Должен сказать, похоже, что кто-то намеренно ввел плохие строки в совершенно приятное решение:
if...else
также убивает его. Очевидно, newlst
не будет равняться l1
, так как к тому времени, как вы сюда попадете, вы проверили только один элемент в большей части l1
- Удалите его.newlst
бесполезным.Дополнения от @Olivier, которые я пропустил
l1
пуста избыточна - цикл будет пропущен, и вы вернетесь TrueЭто фиксированное решение:
def subList(l1, l2):
indexNum = 0
if len(l1) > len(l2): return False
for num in l1:
while indexNum < len(l2):
if l2[indexNum] == num:
indexNum = indexNum + 1
break
indexNum = indexNum + 1
else:
return False
return True
l1 = [15,1,100]
l2 = [20,15,30,50,1,100]
l3 = [15,50,20]
print(subList(l1,l2))
print(subList(l3,l2))
Логика вашего цикла:
l1
.l2
. indexNum
управляет этой indexNum
между итерациями.else
если вы его не нашли, верните False
.True
если вам удалось сделать это для всех элементов в l1
.Ваше решение не простое, но и самое эффективное.
Вы можете решить эту проблему, используя понимание списка и встроенную функцию all(), чтобы проверить, равны ли списки
l1 = [1,3,4]
l2 = [7,9,1,2,1,3,4,9,8,1,3,4,9]
# the length of the looked for list
lenL1=len(l1)
# create all sublists of this length from each starting position of l2 up to its end
# and check if this sublist has exactly the same digits as the l1 list using all()
a = [(l2[i:i+lenL1],i) for i in range(len(l2)-lenL1) \
if all(l1[q]==l2[i+q] for q in range(lenL1))]
print(a)
Выход:
[([1, 3, 4], 4), ([1, 3, 4], 9)]
Он нашел подсписку в столбцах 4 и 9 в l2
Если вы предпочитаете "выписывать" метод вместо понимания списка, вы можете сделать что-то подобное:
def checker(l1,l2):
"""Enuimerates over l2, finds a value thats same as l1[0] and delegates
sublistchecking to inner function checkSame"""
def checkSame(a,b):
"""gets two lists of same length and checks that theire values are identical"""
return all(a[i] == b[i] for i in range(1,len(a))) # 0 was checked already
l1_len = len(l1) # store length so we do not need to lookup it all the time
for idx,value in enumerate(l2):
if value == l1[0]: # check 0
if checkSame(l1,l2[idx:idx+l1_len]):
yield(l1,idx)
print(list(checker(l1,l2)))
Я предпочитаю использовать enumerate(iterable)
если мне нужен индекс во что-то итеративное вместе с значением - перечисление возвращает оба:
[15, 1, 1, 100]
например, с l2, ваш код вернет True неправильно. Такжеif l1 == []: return True
в вашем коде и код @Coop не требуется, пустой список означает нулевую итерацию цикла for, и вы все равно возвращаете True.