2

我有一个包含三个对象的 Python:一个list(例如:标题)和另一个(例如:名称)。tuplesstringdatestring

例子:

scientific_works = [
    ('SW 1', datetime.date(2000, 10, 15), 'auth 1'),
    ('SW 2', datetime.date(2000, 11, 3), 'auth 1'),
    ('SW 3', datetime.date(2000, 11, 4), 'auth 1'),
    ('SW 4', datetime.date(2000, 12, 1), 'auth 1'),
]

然后我有一个模式:

date直到date,(至少)每天/每周/每月/每年的int项目listint

例子:

from  datetime.date(2000, 11, 1)
until datetime.date(2000, 11, 30)
1 item per day

我希望算法做什么:

  • 给定该列表和该模式,过滤后的项目是否符合规则?

在示例的情况下,此模式将匹配 2 个项目,它们都与此处的规则匹配:1 item complete per day,但是,由于没有an item每天块,算法将返回false

另一个例子:

  • 每个 Int_2(天/周/月)是否有(至少)Int_1 数量的项目(作品)?
    • 每天 1 项工作意味着在给定的日期范围内每 1 天块至少有 1 个项目。每周 2 件作品意味着,日期范围内每周(或 7 天块)至少 2 件作品。

当然,我可以遍历列表并找出哪些项目匹配fromuntil模式。

但是,我真的很困惑将它们与其他规则进行匹配以查看它是正匹配还是负匹配。

我的问题:

  • 如何构建算法,为其提供列表和规则模式(每天或每周或每月或每年 x 项),并查看它是否匹配?

如果作者解锁了奖励,我正在为一个应用程序开发一个小组件,其中给定了特定的数据(列表)和规则(模式)。

我已经完成了 udacity 的几个 Python 类,包括大多数算法,但真的找不到解决方法。

到目前为止,我想到了这个:

  1. 过滤具有给定日期范围的列表项。
  2. 计算范围内的范围块:从 d1 到 d2 的 1 天 = 5 天 - 从 d1 到 d2 的 1 周 = 3 周
  3. int在上面计算的范围内创建一个循环。
  4. 在循环的每个步骤中将周、月、年转换为天。
  5. 将金额添加到开始日期并查看项目是否与日期范围匹配。
  6. 将金额添加到日期范围的下一个开始并重复。

但是,这不起作用,我认为将块转换为天根本不是有效的。

谢谢你。

4

3 回答 3

1

你能发布一个更好的例子来说明比赛必须遵循的规则吗?您是否正在寻找每个作者每个时间段的特定数量的项目?或者您是否在一段时间内寻找某些条目,然后找到它们属于谁?这将影响排序。

我认为您最终将不得不对这些数据使用排序算法,如果您以正确的方式进行操作,这并不可怕。

从您问题的底部,我认为如果您在每 n 个时间段(日/周/月)搜索 x 个项目,然后确定作者,这可能会有点混乱。如果您的作者数量有限,则可能更容易翻转它并为每个作者创建一个数组并将项目和日期存储在其中。然后,您只需对每个作者运行一个测试循环,检查他们的所有条目以查看它们是否符合要求。

对于 Python 课程,MIT OpenCourseware 的 6.00 Introduction to Computer Science and Programming 非常好。可在http://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-00-introduction-to-computer-science-and-programming-fall-2008/ >

于 2013-11-09T11:41:03.930 回答
1

我将使用以下设计:迭代工作序列并产生“好”的主生成器函数;以及一组实现特定规则的可插入过滤器,例如日期范围、每天、每周、每月 N 项等。

下面是一个小例子来说明这个想法:

from datetime import date
from pprint import pprint

scientific_works = [
    ('SW 1', date(2000, 10, 15), 'auth 1'),
    ('SW 2', date(2000, 11, 3), 'auth 1'),
    ('SW 3', date(2000, 11, 4), 'auth 1'),
    ('SW 4', date(2000, 11, 5), 'auth 1'),
    ('SW 5', date(2000, 12, 1), 'auth 1'),
    ('SW 6', date(2000, 12, 15), 'auth 1'),
    ('SW 7', date(2000, 12, 18), 'auth 1'),
    ('SW 8', date(2000, 12, 22), 'auth 1'),
]

def filter_works(works, *filters):
    for work in works:
        good = True
        for fil in filters:
            good = good and fil(work)
        if good:
            yield work

class RangeFilter(object):
    def __init__(self, from_date, to_date):
        self.from_date = from_date
        self.to_date = to_date

    def __call__(self, work):
        return self.from_date <= work[1] <= self.to_date


class WorksPerMonthFilter(object):
    def __init__(self, limit):
        self.limit = limit
        self._current_month = date.min
        self._current_number = 0

    def __call__(self, work):
        month = date(work[1].year, work[1].month, 1)
        if month == self._current_month:
            self._current_number += 1
        else:
            self._current_month = month
            self._current_number = 1
        return self._current_number <= self.limit


if __name__ == '__main__':
    pprint(list(filter_works(scientific_works, RangeFilter(date(2000, 10, 1), date(2000, 11, 30)), WorksPerMonthFilter(2))))
    pprint(list(filter_works(scientific_works, RangeFilter(date(2000, 10, 1), date(2000, 12, 31)), WorksPerMonthFilter(2))))
    pprint(list(filter_works(scientific_works, RangeFilter(date(2000, 10, 1), date(2000, 12, 31)), WorksPerMonthFilter(3))))
于 2013-11-09T12:06:18.137 回答
1

如果模式是:

从 start_date
直到 end_date
每期 X 项

然后要找出是否与模式匹配,可以使用函数scientific_works的模拟:numpy.histogram()

import datetime
import numpy as np

ts = datetime.date.toordinal # or any monotonic numeric `date` function 
hist = np.histogram(map(ts, (date for title, date, name in scientific_works)),
                    bins=map(ts, daterange(start_date, end_date, period))[0]
does_it_match = all(x >= X for x in hist)

在哪里:

def daterange(start_date, end_date, period):
    d = start_date
    while d < end_date:
        yield d
        d += period

例子:

>>> from datetime import date, timedelta
>>> list(daterange(date(2000, 1, 1), date(2000, 2, 1), timedelta(days=7)))
[datetime.date(2000, 1, 1), datetime.date(2000, 1, 8),
 datetime.date(2000, 1, 15), datetime.date(2000, 1, 22),
 datetime.date(2000, 1, 29)]
于 2013-11-10T02:38:13.140 回答