首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将dir中的每个项与另一个dir中的每个项进行比较。

将dir中的每个项与另一个dir中的每个项进行比较。
EN

Code Review用户
提问于 2019-04-28 10:42:03
回答 2查看 89关注 0票数 5

任务是比较学生作业SQL文件和导师SQL文件。

我写了两个函数,返回一个二维数组(1元素是绝对路径,2是相对的)。

然后,我将比较学生和导师的相对路径,并执行SQL文件(使用绝对路径查找),如果这些值相等

是否有更优雅的实现?

mentors dir的文件夹结构:

代码语言:javascript
复制
Homework (folder)
  ├ 1 (folder)
  | ├ 1.sql
  | ├ 2.sql
  | └ n.sql
  ├ 2 (folder)
  | ├ 1.sql
  | ├ 2.sql
  | └ n.sql
  ├ n (folder)
  | ├ 1.sql
  | ├ 2.sql
  | └ n.sql

dir的文件夹结构:

代码语言:javascript
复制
├Students Homework (folder)
 ├Student1(folder)
  ├ 1 (folder)
  | ├ 1.sql
  | ├ 2.sql
  | └ n.sql
  ├ 2 (folder)
  | ├ 1.sql
  | ├ 2.sql
  | └ n.sql
  ├ n (folder)
  | ├ 1.sql
  | ├ 2.sql
  | └ n.sql
 ├Student2(folder)
  ├ 1 (folder)
  | ├ 1.sql
  | ├ 2.sql
  | └ n.sql
  ├ 2 (folder)
  | ├ 1.sql
  | ├ 2.sql
  | └ n.sql
  ├ n (folder)
  | ├ 1.sql
  | ├ 2.sql
  | └ n.sql

“导师”职能:

代码语言:javascript
复制
def find_mentors_sql(config):

    mentors_sql_abs = []
    mentors_sql_rel = []

    for dirpath, subdirs, files in walk(config["MAIN_DIR"] + '\\Homework'):
        mentors_sql_abs.extend(path.join(dirpath, x) for x in files if x.endswith(".sql"))
        mentors_sql_rel.extend(path.join(path.basename(dirpath), x) for x in files if x.endswith(".sql"))

    mentors_sql = [[0] * 2 for i in range(len(mentors_sql_abs))]

    iter = 0
    for _ in mentors_sql_abs:
        mentors_sql[iter][0] = mentors_sql_abs[iter]
        iter += 1

    iter1 = 0
    for _ in mentors_sql_rel:
        mentors_sql[iter1][1] = mentors_sql_rel[iter1]
        iter1 += 1

    return mentors_sql

“学生”函数(逻辑类似于前一个:

代码语言:javascript
复制
def find_students_sql(config):

    students_sql_abs = []
    students_sql_rel = []

    for dirpath, subdirs, files in walk(config["MAIN_DIR"] + '\\Students Homework'):
        students_sql_abs.extend(path.join(dirpath, x) for x in files if x.endswith(".sql"))
        students_sql_rel.extend(path.join(path.basename(dirpath), x) for x in files if x.endswith(".sql"))

    students_sql = [[0] * 2 for i in range(len(students_sql_abs))]

    iter = 0
    for _ in students_sql:
        students_sql[iter][0] = students_sql_abs[iter]
        iter += 1

    iter1 = 0
    for _ in students_sql:
        students_sql[iter1][1] = students_sql_rel[iter1]
        iter1 += 1

    return students_sql
```
代码语言:javascript
复制
EN

回答 2

Code Review用户

发布于 2019-04-28 21:10:29

  1. 建议使用enumerate而不是iter (改名为i)、_和索引。对于i,abs_path in enemerate(mentors_sql_abs):mentors_sql = abs_path
  2. 与其手工构建zip,不如使用mentors_sql
  3. 如果您不扩展mentors_sql_*并只扩展yield值,您的函数就可以进一步简化。
  4. 请只使用一个字符串分隔符( '" )。
  5. x是一个非常糟糕的变量名,我会使用file。即使对一个理解来说,它也是相当差的,因为x并不是任何东西的短手。
  6. 当你走不同的路时,这两个函数之间唯一的区别。因此,您可以更改您的输入,以说明这一点,并使用一个函数。
  7. 我不认为有必要返回相对路径和绝对路径,因此不会对其进行过多的评论。您可能需要返回一个并在需要时进行转换。
代码语言:javascript
复制
def find_sql(path):
    for dirpath, subdirs, files in walk(path):
        for file in files:
            if file.endswith('.sql'):
                yield (
                    path.join(dirpath, file),
                    path.join(path.basename(dirpath), file)
                )


mentors = find_sql(config["MAIN_DIR"] + '\\Homework')
students = find_sql(config["MAIN_DIR"] + '\\Students Homework')
票数 2
EN

Code Review用户

发布于 2019-04-28 21:31:33

好吧,我花了一小段时间和你的代码@Valentyn在一起,我认为它基本上没有受到伤害.

sql_utils/__init__.py

代码语言:javascript
复制
import os


def walked_sql_paths(config, sub_dir):
    """
    Generates `tuple` of absolute and relative file paths

    - `config` should contain a 'MAIN_DIR' key with a value similar to
        - `/home/Mentor`
        - `/home/StudentName`
    - `sub_dir` should contain a string such as `Homework`
    """
    ## ... I am guessing that ya might be doing something
    ##     else with the `config` object, if this is not
    ##     the case, then this could be simplified to
    ##     only taking a `path` argument instead.
    target_dir = os.path.join(config['MAIN_DIR'], sub_dir)

    for dirpath, subdirs, files in walk(target_dir):
        for item in files:
            if not item.endswith('.sql'):
                continue

            sql_abs = os.path.join(dirpath, item)
            sql_rel = os.path.basename(dirpath)
            yield sql_abs, sql_rel

""" (三元引号)之间的内容是一个"docstring“,可以通过help(walked_sql_paths)print(walked_sql_paths.__doc__)访问。我不想在这里讨论“迪德”“魔术法”的内容,因为这是一个完整的“另一种蠕虫”。重要的是,可访问的文档是Python允许的,而不需要它的代码则是值得努力的东西。

我在上面的产出量循环中使用了for,这样它就会对任何调用next()__next__()方法(由for循环和其他进程隐式调用)产生部分结果,generators是优化代码以及确保用户在结果之间体验更少异常抖动加载的一种廉价方法;即使需要一段时间,这通常会感觉更快--换句话说。

sql_abssql_rel的赋值首先是为了可读性,其次是为了便于以后做一些类似yield sql_rel, sql_abs的事情。否则,与@Peilonrayz发布的答案相比,没有什么理由更喜欢它。

以下是使用上述修改代码的一种方法..。

代码语言:javascript
复制
from sql_utils import walked_sql_paths


## ... setting of `mentors` and `students` `_config` objects
##     and other stuff I am guessing will go here...


students_paths = walked_sql_paths(config = students_config,
                                  sub_dir = 'Students Homework')

mentors_paths = walked_sql_paths(config = mentors_config,
                                 sub_dir = 'Homework')


for s_paths, m_paths in zip(students_paths, mentors_paths):
    if not s_paths[0] == m_paths[0]:
        print("Warning, continuing past -> {s_rel_path} and {m_rel_path} miss-match!".format(
            s_rel_path = s_path[0],
            m_rel_path = m_path[0]))
        continue

    print("Time to compare -> Mentors {m_abs_path} with Students {s_abs_path}".format(
        m_abs_path = m_paths[1],
        s_abs_path = s_paths[1]))

我使用zip在上面的for循环中压缩两个生成器,因为它是一个内置的,似乎可以满足您的需要。

希望所有这些都不会让人心烦意乱,因为就像我在你问题的评论@Valentyn中说的那样,你真的接近了一些我无法补充的东西。

再仔细看一下文件夹结构,就会发现循环的效果会更好一些。你喜欢点什么?

我的想法是迭代学生的Students_Homework/,然后在子文件夹之间迭代zip_-up,在这种情况下,也许可以在第一次访问时缓存导师的文件夹。但是,如果有很多子目录,那就不是很好的扩展.另一个想法是依次遍历导师的1-n文件夹和zip-up。请随意评论一下哪一个可能更有帮助。

对未来的思考,使用try/except,你可以在Student3没有交出2__'s文件夹中的5.sql文件的情况下编写代码,所以下面是一些框架代码,希望能使您更接近容错性……

代码语言:javascript
复制
def safety_zipper(*iters, search_strs):
  """
  Allows for doing something _clever_ where things could have gone painfully wrong

  - `iters`, `list` of iterables that each output `tuple`s of length two `(rel_path, abs_path)`
  - `search_strs`, `list` of `str`ings to search for matches on `rel_path`

  Yields `list` of `tuple`s `(rel_path, abs_path)`
  """
  for search_str in search_strs:
      partial_results = []
      for thing in iters:
          try:
              path_tuple = thing.next()
          except (GeneratorExit, StopIteration):
              ## Note passing can be dangerous, I only do it
              ##  because the parent loop will exit, eventually
              print("Warning {abs_path} miss-match with {search_str}".format(
                  abs_path = path_tuple[1],
                  search_str = search_str))
              pass
          else:  ## No error so do things with next thing
              ## Uncomment the following if useful
              # abs_path = path_tuple[1]
              rel_path = path_tuple[0]
              if search_str == rel_path:
                  partial_results.append(path_tuple)
                  continue

              ## Deal with miss-matches in a clever way here, such
              ##  as if a student is late to turn in an assignment.

          finally:
              ## Finally runs regardless, well so long as another
              ##  exception is not raised before reaching here.
              ##  Only included for completeness and in-case ya
              ##  wanted to do something fancy here too.
              pass

      yield partial_results

..。我要警告的是,上面的内容并不完整,但本质上它将允许捕获Student目录或文件与Mentor__'s文件路径不匹配的情况。为了能够检查目录和文件中的差异,可能必须对其进行堆叠,而预加载search_strs列表要么需要预先了解,要么需要预解析Mentor_‘S文件路径块来填充。

但是下游的任何东西都会有一个更干净的输入,并且需要更少的边缘检测。

票数 2
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/219302

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档