计算列表中大于其邻居的数字
Counting the numbers in a list that are larger than their neighbors
我想在列表中找到一个峰。
- 我想知道一个数字是否比他的邻居大。
- 如果它是列表中的第一个对象,我只想检查他是否比他后面的对象大。
- 如果它是列表中的最后一个对象,我想检查他之前的对象。
def peaks(lst):
num = 0
leni = len(lst)
print(leni)
for i in range(1,leni - 1):
if lst[i] > lst[i-1] and lst[i] > lst[i+1]:
num = num + 1
for i in range(leni):
print(i)
if i == 0:
if lst[i] > lst[i+1]:
num = num + 1
elif i == leni+1:
if lst[i] > lst[i-1]:
num = num + 1
return num
当它应该检查最后一个对象时,这段代码不起作用。
当我尝试 [1,2,3]
我得到 0
而不是 1
.
您好,欢迎来到 Whosebug!
请注意,range(leni)
是一个从 0 到 leni - 1
的数字序列。所以你的条件 i == leni+1
永远不会满足。您可以将其替换为 i == leni - 1
.
另请注意,您不需要第二个循环。您可以将其替换为
if lst[0] > lst[1]:
num = num + 1
if lst[-1] > lst[-2]:
num= num + 1
此处lst[-1]
与lst[leni - 1]
相同,lst[-2]
与lst[leni - 2]
相同。
应该可以解决问题
def peaks(lst):
lst_len = len(lst)
hits = 0
for i in range(1,lst_len-1):
num_to_test = lst[i]
before = lst[i-1]
after = lst[i+1]
if num_to_test > before and num_to_test > after:
hits+=1
# This is for the case lst contains only 1 member and you want to count it as 1
if lst_len == 1:
hits+=1
# For checking the edges
if lst_len > 1:
if lst[0] > lst[1]:
hits+=1
if lst[lst_len-1] > lst[lst_len-2]:
hits+=1
return hits
您可以通过使边界特殊情况不再那么特殊来做一些技巧来计算峰值:
def peaks(lst):
lst = [float("-inf")] + lst + [float("-inf")]
return sum(a < b > c for a, b, c in zip(lst, lst[1:], lst[2:]))
您似乎刚从 python 开始。您的代码很难理解。这个问题有很多可能的解决方案,但我建议编写简单的代码。然后担心性能。
可读性第一!
from typing import List
def peaks(lst: List[int]):
found = 0
for i, current_value in enumerate(lst):
is_first_object = i == 0
is_last_object = i == len(lst) - 1
if is_first_object:
previous_val = None
else:
previous_val = lst[i-1]
if is_last_object:
next_val = None
else:
next_val = lst[i+1]
if is_first_object and not is_last_object:
found += 1 if current_value > next_val else 0
elif is_last_object and not is_first_object:
found += 1 if current_value > previous_val else 0
elif not is_last_object and not is_last_object:
found += 1 if previous_val < current_value > next_val else 0
return found
print(peaks([1, 2, 3]))
另一种方式。
检查极端然后检查核心,三个三个:
def count_peaks(ls):
res = [ls[0] > ls[1], ls[-1] > ls[-2]]
for n in range(len(ls)-2):
a, b, c = ls[n:n+3]
res.insert(-1, b > max([a, c]))
return res
在最后一个元素之前插入,以反映结果中的峰位置。
因此,在 [1,2,1,2,4,5]
的情况下:
count_peaks([1,2,1,2,4,5])
#=>[False, True, False, False, False, True]
只需 return sum(res)
即可获得所需结果:2
你可以在前面和最后添加第一个元素和倒数第二个元素的代理值,然后检查从第一个元素到倒数第二个元素的条件
def peaks(array):
if len(array)<2:
return 0
array2 = [array[1]] + array + [array[-2]]
count = sum([1 for i in range(len(array2)-2) if array2[i+2]<array2[i+1] >array2[i]])
return count
试试这个
def peaks(lst):
num = 0
leni = len(lst)
for i in range(leni):
if i == 0:
if lst[i] > lst[i+1]:
num = num + 1
elif i == leni-1:
if lst[i] > lst[i-1]:
num = num + 1
else:
if lst[i] > lst[i-1] and lst[i] > lst[i+1]:
num = num + 1
return num
直接相邻峰的计数可能是一项与性能相关的任务,实现列表越来越长。比较 运行 时间的充分理由。在第一个 运行 中,我决定只使用一个测试集。显然,不同的实现可能会在不同长度的列表中显示出它们的优势。例如,边界值处理的最佳实现似乎是一个取决于列表长度的候选者。
输出:
count_peaks_schwobaseggl: elapsed time 1.44 s
count_peaks_sahasrara62: elapsed time 1.50 s
count_peaks_saikat: elapsed time 2.27 s
count_peaks_tom_wojcik: elapsed time 4.11 s
count_peaks_igian: elapsed time 3.65 s
count_peaks_cloud_balancing: elapsed time 1.86 s
实施:
import random
import time
from typing import List
def measure_runtime_in_s(func, test_lists):
start = time.time()
results = []
for test_list in test_lists:
max_cnt = func(test_list)
results.append(max_cnt)
return time.time() - start, results
def run_experiment(funcs, nlists=1000, len_range=(20, 10000), num_range=(-100, 100)):
assert len(funcs) > 0
# generate test data
test_lists = [[random.randint(*num_range) for _ in range(random.randint(*len_range))]
for _ in range(nlists)]
# run it for all implementations and check results
_, ref_results = measure_runtime_in_s(funcs[0], test_lists)
for func in funcs:
failed = False
time_in_s, results = measure_runtime_in_s(func, test_lists)
if not all(result == ref_result for result, ref_result in zip(results, ref_results)):
failed = True
print(
f"{func.__name__}: elapsed time {time_in_s:.2f} s"
+ (" (FAILED TESTS!)" if failed else ""))
def count_peaks_schwobaseggl(lst):
lst = [float("-inf")] + lst + [float("-inf")]
return sum(a < b > c for a, b, c in zip(lst, lst[1:], lst[2:]))
def count_peaks_sahasrara62(array):
if len(array) < 2:
return 0
array2 = [array[1]] + array + [array[-2]]
count = sum([1 for i in range(len(array2) - 2) if array2[i + 2] < array2[i + 1] > array2[i]])
return count
def count_peaks_saikat(lst):
num = 0
leni = len(lst)
for i in range(leni):
if i == 0:
if lst[i] > lst[i + 1]:
num = num + 1
elif i == leni - 1:
if lst[i] > lst[i - 1]:
num = num + 1
else:
if lst[i] > lst[i - 1] and lst[i] > lst[i + 1]:
num = num + 1
return num
def count_peaks_igian(ls):
res = [ls[0] > ls[1], ls[-1] > ls[-2]]
for n in range(len(ls)-2):
a, b, c = ls[n:n+3]
res.insert(-1, b > max([a, c]))
return sum(res) # < modified
def count_peaks_tom_wojcik(lst: List[int]):
found = 0
for i, current_value in enumerate(lst):
is_first_object = i == 0
is_last_object = i == len(lst) - 1
if is_first_object:
previous_val = None
else:
previous_val = lst[i-1]
if is_last_object:
next_val = None
else:
next_val = lst[i+1]
if is_first_object and not is_last_object:
found += 1 if current_value > next_val else 0
elif is_last_object and not is_first_object:
found += 1 if current_value > previous_val else 0
elif not is_last_object and not is_last_object:
found += 1 if previous_val < current_value > next_val else 0
return found
def count_peaks_cloud_balancing(lst):
lst_len = len(lst)
hits = 0
for i in range(1, lst_len - 1):
num_to_test = lst[i]
before = lst[i - 1]
after = lst[i + 1]
if num_to_test > before and num_to_test > after:
hits += 1
# This is for the case lst contains only 1 member and you want to count it as 1
if lst_len == 1:
hits += 1
# For checking the edges
if lst_len > 1:
if lst[0] > lst[1]:
hits += 1
if lst[lst_len - 1] > lst[lst_len - 2]:
hits += 1
return hits
if __name__ == "__main__":
run_experiment([
count_peaks_schwobaseggl,
count_peaks_sahasrara62,
count_peaks_saikat,
count_peaks_tom_wojcik,
count_peaks_igian,
count_peaks_cloud_balancing,
])
我想在列表中找到一个峰。
- 我想知道一个数字是否比他的邻居大。
- 如果它是列表中的第一个对象,我只想检查他是否比他后面的对象大。
- 如果它是列表中的最后一个对象,我想检查他之前的对象。
def peaks(lst):
num = 0
leni = len(lst)
print(leni)
for i in range(1,leni - 1):
if lst[i] > lst[i-1] and lst[i] > lst[i+1]:
num = num + 1
for i in range(leni):
print(i)
if i == 0:
if lst[i] > lst[i+1]:
num = num + 1
elif i == leni+1:
if lst[i] > lst[i-1]:
num = num + 1
return num
当它应该检查最后一个对象时,这段代码不起作用。
当我尝试 [1,2,3]
我得到 0
而不是 1
.
您好,欢迎来到 Whosebug!
请注意,range(leni)
是一个从 0 到 leni - 1
的数字序列。所以你的条件 i == leni+1
永远不会满足。您可以将其替换为 i == leni - 1
.
另请注意,您不需要第二个循环。您可以将其替换为
if lst[0] > lst[1]:
num = num + 1
if lst[-1] > lst[-2]:
num= num + 1
此处lst[-1]
与lst[leni - 1]
相同,lst[-2]
与lst[leni - 2]
相同。
应该可以解决问题
def peaks(lst):
lst_len = len(lst)
hits = 0
for i in range(1,lst_len-1):
num_to_test = lst[i]
before = lst[i-1]
after = lst[i+1]
if num_to_test > before and num_to_test > after:
hits+=1
# This is for the case lst contains only 1 member and you want to count it as 1
if lst_len == 1:
hits+=1
# For checking the edges
if lst_len > 1:
if lst[0] > lst[1]:
hits+=1
if lst[lst_len-1] > lst[lst_len-2]:
hits+=1
return hits
您可以通过使边界特殊情况不再那么特殊来做一些技巧来计算峰值:
def peaks(lst):
lst = [float("-inf")] + lst + [float("-inf")]
return sum(a < b > c for a, b, c in zip(lst, lst[1:], lst[2:]))
您似乎刚从 python 开始。您的代码很难理解。这个问题有很多可能的解决方案,但我建议编写简单的代码。然后担心性能。
可读性第一!
from typing import List
def peaks(lst: List[int]):
found = 0
for i, current_value in enumerate(lst):
is_first_object = i == 0
is_last_object = i == len(lst) - 1
if is_first_object:
previous_val = None
else:
previous_val = lst[i-1]
if is_last_object:
next_val = None
else:
next_val = lst[i+1]
if is_first_object and not is_last_object:
found += 1 if current_value > next_val else 0
elif is_last_object and not is_first_object:
found += 1 if current_value > previous_val else 0
elif not is_last_object and not is_last_object:
found += 1 if previous_val < current_value > next_val else 0
return found
print(peaks([1, 2, 3]))
另一种方式。
检查极端然后检查核心,三个三个:
def count_peaks(ls):
res = [ls[0] > ls[1], ls[-1] > ls[-2]]
for n in range(len(ls)-2):
a, b, c = ls[n:n+3]
res.insert(-1, b > max([a, c]))
return res
在最后一个元素之前插入,以反映结果中的峰位置。
因此,在 [1,2,1,2,4,5]
的情况下:
count_peaks([1,2,1,2,4,5])
#=>[False, True, False, False, False, True]
只需 return sum(res)
即可获得所需结果:2
你可以在前面和最后添加第一个元素和倒数第二个元素的代理值,然后检查从第一个元素到倒数第二个元素的条件
def peaks(array):
if len(array)<2:
return 0
array2 = [array[1]] + array + [array[-2]]
count = sum([1 for i in range(len(array2)-2) if array2[i+2]<array2[i+1] >array2[i]])
return count
试试这个
def peaks(lst):
num = 0
leni = len(lst)
for i in range(leni):
if i == 0:
if lst[i] > lst[i+1]:
num = num + 1
elif i == leni-1:
if lst[i] > lst[i-1]:
num = num + 1
else:
if lst[i] > lst[i-1] and lst[i] > lst[i+1]:
num = num + 1
return num
直接相邻峰的计数可能是一项与性能相关的任务,实现列表越来越长。比较 运行 时间的充分理由。在第一个 运行 中,我决定只使用一个测试集。显然,不同的实现可能会在不同长度的列表中显示出它们的优势。例如,边界值处理的最佳实现似乎是一个取决于列表长度的候选者。
输出:
count_peaks_schwobaseggl: elapsed time 1.44 s
count_peaks_sahasrara62: elapsed time 1.50 s
count_peaks_saikat: elapsed time 2.27 s
count_peaks_tom_wojcik: elapsed time 4.11 s
count_peaks_igian: elapsed time 3.65 s
count_peaks_cloud_balancing: elapsed time 1.86 s
实施:
import random
import time
from typing import List
def measure_runtime_in_s(func, test_lists):
start = time.time()
results = []
for test_list in test_lists:
max_cnt = func(test_list)
results.append(max_cnt)
return time.time() - start, results
def run_experiment(funcs, nlists=1000, len_range=(20, 10000), num_range=(-100, 100)):
assert len(funcs) > 0
# generate test data
test_lists = [[random.randint(*num_range) for _ in range(random.randint(*len_range))]
for _ in range(nlists)]
# run it for all implementations and check results
_, ref_results = measure_runtime_in_s(funcs[0], test_lists)
for func in funcs:
failed = False
time_in_s, results = measure_runtime_in_s(func, test_lists)
if not all(result == ref_result for result, ref_result in zip(results, ref_results)):
failed = True
print(
f"{func.__name__}: elapsed time {time_in_s:.2f} s"
+ (" (FAILED TESTS!)" if failed else ""))
def count_peaks_schwobaseggl(lst):
lst = [float("-inf")] + lst + [float("-inf")]
return sum(a < b > c for a, b, c in zip(lst, lst[1:], lst[2:]))
def count_peaks_sahasrara62(array):
if len(array) < 2:
return 0
array2 = [array[1]] + array + [array[-2]]
count = sum([1 for i in range(len(array2) - 2) if array2[i + 2] < array2[i + 1] > array2[i]])
return count
def count_peaks_saikat(lst):
num = 0
leni = len(lst)
for i in range(leni):
if i == 0:
if lst[i] > lst[i + 1]:
num = num + 1
elif i == leni - 1:
if lst[i] > lst[i - 1]:
num = num + 1
else:
if lst[i] > lst[i - 1] and lst[i] > lst[i + 1]:
num = num + 1
return num
def count_peaks_igian(ls):
res = [ls[0] > ls[1], ls[-1] > ls[-2]]
for n in range(len(ls)-2):
a, b, c = ls[n:n+3]
res.insert(-1, b > max([a, c]))
return sum(res) # < modified
def count_peaks_tom_wojcik(lst: List[int]):
found = 0
for i, current_value in enumerate(lst):
is_first_object = i == 0
is_last_object = i == len(lst) - 1
if is_first_object:
previous_val = None
else:
previous_val = lst[i-1]
if is_last_object:
next_val = None
else:
next_val = lst[i+1]
if is_first_object and not is_last_object:
found += 1 if current_value > next_val else 0
elif is_last_object and not is_first_object:
found += 1 if current_value > previous_val else 0
elif not is_last_object and not is_last_object:
found += 1 if previous_val < current_value > next_val else 0
return found
def count_peaks_cloud_balancing(lst):
lst_len = len(lst)
hits = 0
for i in range(1, lst_len - 1):
num_to_test = lst[i]
before = lst[i - 1]
after = lst[i + 1]
if num_to_test > before and num_to_test > after:
hits += 1
# This is for the case lst contains only 1 member and you want to count it as 1
if lst_len == 1:
hits += 1
# For checking the edges
if lst_len > 1:
if lst[0] > lst[1]:
hits += 1
if lst[lst_len - 1] > lst[lst_len - 2]:
hits += 1
return hits
if __name__ == "__main__":
run_experiment([
count_peaks_schwobaseggl,
count_peaks_sahasrara62,
count_peaks_saikat,
count_peaks_tom_wojcik,
count_peaks_igian,
count_peaks_cloud_balancing,
])