计算给定窗口w1的滚动平均值和滚动最大值。 但使用是: 您应该编写一个接受迭代器的类,并充当生成元组的生成器,如上所示。
例如,给定包含以下值的流。 W = 3。
[1, 2, 3, 4, 5, 6]
预计会出现以下元组,其中“无”表示某个值不可用,并且在某些语言中为“NaN”:
(None, None) -- When we have input 1 --- As we dont have w num, ignore - None
(None, None) -- Now we have input 1,2
(2, 3) -- Now we have input 1,2,3
(3, 4) -- Discard 1. Window [2,3,4]
(4, 5) -- Discard 3. Window [3,4,5]
(5, 6) -- Discard 4. Window [4,5,6]
在这个元组中,第一个数字是平均w(= 3)个数。第二 num是w(= 3)个数的最大值。
我仍然在python中学习iterator和generator / yield。
Que:那么生成器接受整个序列(或迭代器/列表)?如果 seq是巨大的?
我编写的简单解决方案可能不是有效的算法,但无论如何 我想首先知道这是否适用于发电机:
7 from collections import deque
8 class Solution:
9 def sliding_window_avg_max(self, nums, w=3):
10 d = deque(maxlen = w)
11 total = 0
12 for n in nums:
13 if len(d) >= w:
14 total = total - d.pop() + n
15 else:
16 total = total + n
17 d.append(n)
18 if len(d) >= w:
19 yield (total/float(w), max(d))
20 else:
21 yield(None, None)
22
23 s = Solution()
24 a = [1, 2, 3, 4, 5, 6]
25 for t in s.sliding_window_avg_max(a):
26 print t
编辑: 这不是作业问题。这是我想要的面试问题 也了解其他人的想法。我真的想知道生成器如何帮助 - 不是它需要列表(nums)在内存中吗? 如果我们应该如何使用迭代器呢?
答案 0 :(得分:0)
我会把你的方法分成:
这有两个原因。首先,在这种情况下,编码时间是有限的,如果您只是检查正确的交付,将更容易调试生成器。其次,它是一种更灵活的方法 - 如果采访者要求添加最小和标准偏差,那么它只是计算模块中的几行。
答案 1 :(得分:0)
您应该能够将其转换为类,或将其作为方法添加到类中。
def sliding_window_avg_max(nums, w=3):
if w < 1:
raise ValueError('Window size must be > 0')
for i in range(1, len(nums)+1):
if i < w:
yield None, None
else:
yield sum(nums[i-w:i])/float(w), max(nums[i-w:i])
>>> for t in sliding_window_avg_max([1, 2, 3, 4, 5, 6]):
... print t
(None, None)
(None, None)
(2.0, 3)
(3.0, 4)
(4.0, 5)
(5.0, 6)
答案 2 :(得分:0)
请注意,规范说明(强调我的):
你应该写一个接受迭代器的类,作为一个 生成器,它产生如上所示的元组。
我认为你误解了这个问题;我怀疑你被要求实施the iterator protocol。一种可能的解决方案看起来像这样:
from collections import deque
class Solution(object):
"""Apply a moving window to an iterator, calculate max and average.
Arguments:
iter_ (iterator): The iterator to process.
w (int): The length of the moving window to apply.
Attributes:
window (deque): The moving window.
Example:
>>> list(Solution(range(1, 7), 3))
[(None, None), (None, None), (2, 3), (3, 4), (4, 5), (5, 6)]
"""
def __init__(self, iter_, w):
self.iter = iter(iter_)
self.w = w
self.window = deque(maxlen=w)
def __iter__(self):
return self
def next(self):
"""Calculate the next value in the series.
Notes:
If the window isn't full, return (None, None).
"""
self.window.append(next(self.iter))
if len(self.window) == self.w:
return self._avg(), self._max()
return None, None
def _max(self):
"""Calculate the maximum of the current window."""
return max(self.window)
def _avg(self):
"""Calculate the average of the current window."""
return int(sum(self.window) / float(len(self.window)))
请注意,您也可以将__iter__
作为生成器实施,即删除next
并执行:
def __iter__(self):
for val in self.iter:
self.window.append(val)
if len(self.window) == self.w:
yield self._avg(), self._max()
else:
yield None, None
无论哪种方式,您都要确保从__iter__
返回的是迭代器!
你的解决方案的形式应该让你停下来;根据{{3}},如果您的班级实施了__init__
和另一种方法(在这种情况下甚至不是__init__
!),则它不应该是一个班级。