python 集合操作 set

本文介绍了Python中Set的基本概念及使用方法,包括如何创建、添加、删除元素,以及进行集合间的并集、交集、差集等运算,并通过实例展示了如何利用Set去除列表中的重复元素。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  1. 发现在用python进行机器学习数据挖掘的时候经常用到set,在网上收了一些资料。

  2. http://blog.youkuaiyun.com/business122/article/details/7541486
  3. http://www.cnblogs.com/xiaoit/p/4045547.html

  4. set的内部结构和dict很像,主要区别是不存储value,因此,判断一个元素是否在set中速度很快。
  5. set存储的元素和dict的key类似,必须是不变对象,因此,任何可变对象是不能放入set中的。

    最后,set存储的元素也是没有顺序的。

  6. 假设我们让用户输入星期一至星期日的某天,如何判断用户的输入是否是一个有效的星期呢?

  7. 如果事先创建好一个set,包含'MON' ~ 'SUN':

     

    1
    2
    3
    4
    5
    6
    weekdays = set(['MON''TUE''WED''THU''FRI''SAT''SUN'])
    = 'MON' # 用户输入的字符串
    if in weekdays:
        print ('input ok')
    else:
        print ('input error')

  8. 下面来点简单的小例子说明把。  
  9.   
  10. >>> set('spam' 
  11. >>> set(['h','a','m'])  
  12. >>> x,  
  13. (set(['a''p''s''m']), set(['a''h''m']))  
  14.   
  15. 再来些小应用。  
  16.   
  17. >>> 交集  
  18. set(['a''m'])  
  19.   
  20. >>> 并集  
  21. set(['a''p''s''h''m'])  
  22.   
  23. >>> 差集  
  24. set(['p''s'])  
  25.   
  26. 记得以前个网友提问怎么去除海量列表里重复元素,用hash来解决也行,只不过感觉在性能上不是很高,用set解决还是很不错的,示例如下:  
  27.   
  28. >>> [11,22,33,44,11,22 
  29. >>> set(a)  
  30. >>>  
  31. set([33114422])  
  32. >>> [i for in b]  
  33. >>>  
  34. [33114422 
  35.   

  36.   
  37. 集合支持一系列标准操作,包括并集、交集、差集和对称差集,例如:  
  38.   
  39.    
  40.   
  41.          和 s的并集  
  42.   
  43.          和 s的交集  
  44.   
  45. –          求差集(项在t中,但不在s中)  
  46.   
  47.          对称差集(项在t或s中,但不会同时出现在二者中)  
  48.   
  49.    
  50.   
  51. 基本操作:  
  52.   
  53. t.add('x'           添加一项  
  54.   
  55. s.update([10,37,42])  在s中添加多项  
  56.   
  57. 使用remove()可以删除一项:  
  58.   
  59. t.remove('H')  
  60.   
  61. len(s)  
  62. set 的长度  
  63.   
  64. in  
  65. 测试 是否是 的成员  
  66.   
  67. not in  
  68. 测试 是否不是 的成员  
  1. #子集运算  
  2. >>> set([1,2,3,4,5])  
  3. >>> set([1,2,3])  
  4. >>> s.issubset(t)   #s是否为t的子集,相当于s<=t  
  5. False  
  6. >>> t.issubset(s)  #t是否为s的子集,相当于s>=t  
  7. True  
  8. >>> s<=t  
  9. False  
  10. >>> t<=s  
  11. True  
  12. >>> s
  13. False  
  14. >>> s>t  
  15. True  
  16. >>> s==t  
  17. False  
  18. >>> set([1,2,3])  
  19. >>> x==t            #两set是否相等  
  20. True  

对比frozenset:

frozenset:元素一经创建,不可增加、删除和修改。
不可变集合frozenset的元素可作为字典的键,但可变集合set就不行了。

还有一点需要注意,不管是set还是frozenset,Python都不支持创建一个整数的集合。

seta=set(1) #错误
setb=set('1')#正确
<think>我们面对的任务是:使用Python分析和整理多个Markdown文件之间的关系,这些Markdown文件是由HTML转换而来的。目标:整理这些Markdown文件之间的关系(例如,文件之间的引用关系、链接关系、内容相似性等)步骤:1.读取多个Markdown文件。2.分析文件之间的链接(超链接)关系,因为Markdown中常见的文件间关系是通过链接建立的。3.分析文件之间的内容相似性(可选,用于内容归类)。4.构建文件关系图(有向图,例如文件A链接到文件B)。工具选择:-读取Markdown文件:可以使用`python-frontmatter`(如果关心元数据)或者直接读取文件内容。-解析Markdown中的链接:可以使用正则表达式,或者使用Markdown解析器(如`mistune`、`markdown-it-py`)来获取链接。-分析内容相似性:可以使用TF-IDF向量化然后计算余弦相似度(通过`sklearn`库)。-构建关系图:可以使用`networkx`库来构建图,并进行分析。具体步骤:步骤1:读取多个Markdown文件给定一个文件夹,读取所有.md文件。步骤2:提取链接每个Markdown文件中可能包含两种链接:-外部链接(我们不关心,但需要区分)-内部链接(指向其他Markdown文件或同一文件夹下的其他资源)注意:内部链接可能使用相对路径。因此,我们需要将相对路径转换为绝对路径(相对于项目根目录),或者至少转换为统一的标识(例如文件名)。步骤3:构建链接关系图创建一个有向图,节点是文件,边表示链接关系(A->B表示A中包含了指向B的链接)。步骤4:内容相似性分析(可选)如果需要按内容归类,可以计算文件之间的内容相似度。步骤5:分析关系-找出没有入边的节点(没有被任何文件引用的文件)-找出没有出边的节点(不引用任何文件的文件)-找出强连通分量(循环引用的文件组)-其他图分析步骤6:输出结果(例如关系图的可视化,或者关系报告)实现细节:1.使用`pathlib`遍历目录读取所有Markdown文件:```pythonfrompathlibimportPathmd_files=list(Path("your_directory").glob("**/*.md"))```2.解析Markdown中的链接:我们可以使用正则表达式来提取链接,Markdown链接格式为:`[文本](链接)`。正则表达式:`r'\[[^\]]*\]\(([^\)]*)\)'`但是注意,可能还有图片链接,格式相同,但以`!`开头。如果不想包括图片,我们可以过滤掉以`!`开头的模式?或者我们可以先解析整个链接,然后根据需求决定是否排除图片。另外,我们可能遇到自动链接:`<http://example.com>`,但这种情况较少指向内部文件。3.处理相对路径:当我们提取到链接后,需要判断该链接是否指向一个本地Markdown文件(通常以`.md`结尾)。如果是相对路径,我们可以使用当前Markdown文件所在的路径来解析出目标文件的绝对路径。例如:在`/path/to/file1.md`中有一个链接`[link](subdir/file2.md)`那么目标文件就是`/path/to/subdir/file2.md`。4.构建图:我们将每个文件的绝对路径作为节点。对于文件A中的每个指向内部Markdown文件的链接,如果目标文件存在,则添加一条边A->B(B为目标文件)。5.内容相似性分析:我们可以将每个文件的内容(去除元数据)作为字符串,然后使用TfidfVectorizer转换为向量,再计算余弦相似度。6.可视化:可以使用`networkx`和`matplotlib`绘制图,但节点多时可能不清晰。也可以输出为Graphviz的dot格式,或者使用其他工具。代码结构:我们将创建一个类`MarkdownRelationshipAnalyzer`,包含以下方法:-`__init__(self,root_dir)`-`load_files(self)`:加载所有Markdown文件,建立文件路径列表。-`extract_links(self,content)`:从一个文件内容中提取所有链接(不包括图片)。-`resolve_path(self,current_path,link)`:将相对链接转换为绝对路径。-`build_link_graph(self)`:构建链接关系图。-`analyze_content_similarity(self)`:内容相似性分析(可选)。-`analyze_graph(self)`:分析图结构(如孤岛文件、循环引用等)。-`visualize_graph(self)`:可视化图。开始编码(示例代码):注意:我们将使用networkx构建图,并安装必要的库:-networkx-matplotlib-sklearn(可选,用于相似性分析)由于用户可能有多个文件,且文件数量可能很大,我们仅构建链接关系图。我们决定忽略图片链接,只考虑普通链接(即不包含开头的`!`)。同时,我们只处理指向本地Markdown文件的链接(以`.md`结尾)。示例代码:```pythonimportreimportnetworkxasnxfrompathlibimportPathimportmatplotlib.pyplotaspltclassMarkdownRelationshipAnalyzer:def__init__(self,root_dir):self.root_dir=Path(root_dir).resolve()self.files=[]#存储找到的Markdown文件路径(绝对路径)self.graph=nx.DiGraph()self.file_contents={}#文件路径到文件内容的映射(可选,用于内容分析)defload_files(self):"""加载所有Markdown文件"""self.files=list(self.root_dir.glob('**/*.md'))#将文件路径转为绝对路径self.files=[f.resolve()forfinself.files]#创建文件路径集合,用于快速查找self.file_set=set(self.files)defextract_links(self,content):"""从Markdown内容中提取普通链接的URL(排除图片链接)"""#匹配模式:[文本](链接)但不匹配![文本](链接)pattern=r'(?<!!)\[.*?\]\(.*?\)'#但上面的模式会匹配整段,我们还需要提取括号内的链接#改进:我们分两步:先匹配链接模式,然后提取URLlink_pattern=r'(?<!!)\[.*?\]\((.*?)\)'links=re.findall(link_pattern,content)#注意:链接中可能包含空格,所以不要用\s来分割#返回所有链接returnlinksdefresolve_path(self,current_file,link_path):"""解析相对路径,返回绝对路径(如果指向本地文件)"""#链接可能是一个URL,也可能是本地路径#判断:如果包含://,则是URL,我们忽略if'://'inlink_path:returnNone#当前文件所在目录current_dir=current_file.parent#链接可能是绝对路径(相对于项目根目录)或相对路径#先尝试相对于当前文件所在目录解析target_path=(current_dir/link_path).resolve()#如果路径指向一个目录,那么我们尝试在该目录下寻找index.mdiftarget_path.is_dir():#检查是否有index.mdindex_md=target_path/'index.md'ifindex_md.exists():returnindex_mdelse:returnNone#如果指向的文件存在,则返回iftarget_path.exists()andtarget_path.is_file():returntarget_path#如果目标路径不存在,则尝试加上.md扩展名ifnottarget_path.suffix:#如果没有后缀名,我们加上.mdtarget_path=target_path.with_suffix('.md')iftarget_path.exists():returntarget_path#如果还不存在,我们检查是否有其他扩展名的文件(如.html)?但这里我们只关心.md文件#所以,如果存在.md文件,我们返回,否则返回Noneifnottarget_path.exists():returnNonedefbuild_link_graph(self):"""构建链接关系图"""self.graph=nx.DiGraph()#添加所有文件节点forfileinself.files:self.graph.add_node(file)#处理每个文件forfileinself.files:content=file.read_text(encoding='utf-8')links=self.extract_links(content)forlinkinlinks:#解析链接,得到目标文件target=self.resolve_path(file,link)iftargetandtargetinself.file_set:#添加边:file->targetself.graph.add_edge(file,target)defanalyze_graph(self):"""分析图结构并打印结果"""#找出孤岛节点(没有入边的节点)即没有被任何文件引用的文件orphan_nodes=[nodefornodeinself.graph.nodes()ifself.graph.in_degree(node)==0]print(f"孤岛文件(未被任何文件引用):{len(orphan_nodes)}")fornodeinorphan_nodes:print(f"-{node.relative_to(self.root_dir)}")#找出没有出边的节点(不引用任何其他文件的节点)terminal_nodes=[nodefornodeinself.graph.nodes()ifself.graph.out_degree(node)==0]print(f"终端文件(不引用任何文件):{len(terminal_nodes)}")#找出强连通分量(循环引用)sccs=list(nx.strongly_connected_components(self.graph))cycles=[compforcompinsccsiflen(comp)>1]print(f"存在循环引用的文件组数:{len(cycles)}")fori,compinenumerate(cycles):print(f"循环组#{i+1}:")fornodeincomp:print(f"-{node.relative_to(self.root_dir)}")defvisualize_graph(self,output_file="graph.png"):"""可视化图并保存为图片"""#由于节点是路径对象,我们要转换为相对路径字符串以显示pos=nx.spring_layout(self.graph)nx.draw(self.graph,pos,with_labels=True,labels={node:str(node.relative_to(self.root_dir))fornodeinself.graph.nodes()},font_size=8,node_size=500)plt.savefig(output_file,dpi=300)plt.close()defrun(self):self.load_files()self.build_link_graph()self.analyze_graph()self.visualize_graph()#使用if__name__=="__main__":analyzer=MarkdownRelationshipAnalyzer("/path/to/your/markdown/files")analyzer.run()```注意事项:-由于实际链接可能多样(可能包含锚点#,或者查询参数?),我们可能需要在解析链接时去除这些部分(只保留路径部分)?例如:`file.md#section`->我们只关心`file.md`。-但是,同一个文件内跳转不构成文件间关系。所以我们可以考虑在解析链接后,将锚点部分去掉(如果存在)。修改`resolve_path`函数:在解析之前,我们可以将链接分割,取路径部分。在`extract_links`之后,我们可以:link=link.split('#')[0]#去掉锚点link=link.split('?')[0]#去掉查询参数-另外,我们可能遇到指向目录的链接(但以`/`结尾),这时候按照我们上面的逻辑,会查找目录下的index.md。改进代码:在提取链接后,我们可以做清洗:```python#在extract_links返回的每个link上:#去除锚点和查询参数cleaned_links=[]forlinkinlinks:#如果链接以#开头,可能是锚点链接(同一文件内),跳过iflink.startswith('#'):continue#分割锚点和参数link=link.split('#')[0].split('?')[0]#如果链接为空,跳过ifnotlink.strip():continuecleaned_links.append(link)returncleaned_links```这样,我们可以更精确地获取文件路径。以上代码提供了一个基础框架。根据实际需求,可能需要进一步调整。由于用户提到这些Markdown是由HTML转换而来,链接可能保留着HTML中的特性。但我们的清洗步骤已经处理了锚点和参数。接下来,回答用户的问题:用户需求:使用Python对多个Markdown文件进行操作,整理它们之间的关系(特别是由HTML转换而来的)。我们已经提供了一种基于链接关系的方法,并实现了图分析和可视化。此外,如果需要基于内容相似性(比如聚类),我们可以添加以下方法:```pythonfromsklearn.feature_extraction.textimportTfidfVectorizerfromsklearn.metrics.pairwiseimportcosine_similaritydefanalyze_content_similarity(self):"""构建每个文件的TF-IDF向量,并计算相似度矩阵"""#从文件读取内容(如果还没有读)self.load_files()#确保已经加载了文件路径#读取文件内容(去掉元数据?如果由html2md转换而来,可能没有元数据)contents=[]forfileinself.files:#假设文件是普通markdown内容text=file.read_text(encoding='utf-8')self.file_contents[file]=textcontents.append(text)#使用TfidfVectorizervectorizer=TfidfVectorizer()tfidf_matrix=vectorizer.fit_transform(contents)#计算余弦相似度self.similarity_matrix=cosine_similarity(tfidf_matrix,tfidf_matrix)#相似度矩阵的行列索引对应self.files中的顺序deffind_most_similar(self,file,top_n=5):"""找到与指定文件最相似的文件(排除自己)"""idx=self.files.index(file)sim_scores=list(enumerate(self.similarity_matrix[idx]))#按相似度降序排序sim_scores=sorted(sim_scores,key=lambdax:x[1],reverse=True)#取前top_n+1(因为自己会排在第一)#跳过自身(相似度1.0)top_indices=[ifori,scoreinsim_scores[1:top_n+1]]return[(self.files[i],self.similarity_matrix[idx][i])foriintop_indices]```最后,根据用户需求,可以生成一些相关问题:§§相关问题§§1.如何提高Markdown文件间链接分析的准确性?2.除了链接关系,还有哪些方法可以分析Markdown文件间的关系?3.如何将多个Markdown文件中的链接批量修改为新的路径?4.如何识别并修复Markdown文件中失效的链接?</think> 我将详细解释如何使用Python分析和整理多个Markdown文件之间的关系,特别关注从HTML转换而来的文件。 ### 解决方案:分析和整理Markdown文件关系 #### 1. 建立文件关系图谱 使用图结构表示文件间的引用关系: ```python import re from pathlib import Path import networkx as nx import matplotlib.pyplot as plt class MarkdownRelationshipAnalyzer: def __init__(self, directory): self.directory = Path(directory) self.graph = nx.DiGraph() self.file_contents = {} def load_markdown_files(self): for md_file in self.directory.glob("**/*.md"): content = md_file.read_text(encoding='utf-8') self.file_contents[str(md_file)] = content self.graph.add_node(str(md_file)) def analyze_links(self): # 正则表达式匹配Markdown中的内部链接 link_pattern = r'\[.*?\]\((?!http|www|@)(.*?)\)' for file_path, content in self.file_contents.items(): links = re.findall(link_pattern, content) for link in links: # 解析相对路径为绝对路径 abs_link = (Path(file_path).parent / link).resolve() if abs_link.exists() and abs_link.suffix == '.md': self.graph.add_edge(file_path, str(abs_link)) def visualize_relationships(self): plt.figure(figsize=(12, 8)) pos = nx.spring_layout(self.graph) nx.draw(self.graph, pos, with_labels=True, font_size=8, node_size=1000, node_color='lightblue', arrowsize=10) plt.title("Markdown文件关系图") plt.savefig('file_relationships.png', dpi=300) # 使用示例 analyzer = MarkdownRelationshipAnalyzer("markdown_files/") analyzer.load_markdown_files() analyzer.analyze_links() analyzer.visualize_relationships() ``` #### 2. 内容相似性分析 使用TF-IDF计算文件内容相似度: ```python from sklearn.feature_extraction.text import TfidfVectorizer from sklearn.metrics.pairwise import cosine_similarity def analyze_content_similarity(markdown_files): # 提取纯文本内容(去除Markdown标记) contents = [] for file_path in markdown_files: content = markdown_files[file_path] # 去除Markdown标记 text_only = re.sub(r'[#*!\[\]()><_~`-]', ' ', content) contents.append(text_only) # 计算TF-IDF向量 vectorizer = TfidfVectorizer() tfidf_matrix = vectorizer.fit_transform(contents) # 计算余弦相似度矩阵 similarity_matrix = cosine_similarity(tfidf_matrix) # 找到高相似度文件对 high_similarity_pairs = [] for i in range(len(contents)): for j in range(i+1, len(contents)): if similarity_matrix[i][j] > 0.7: file_i = list(markdown_files.keys())[i] file_j = list(markdown_files.keys())[j] high_similarity_pairs.append((file_i, file_j, similarity_matrix[i][j])) return high_similarity_pairs # 使用示例 similarity_results = analyze_content_similarity(analyzer.file_contents) for file1, file2, similarity in similarity_results: print(f"{file1} 和 {file2} 相似度: {similarity:.2f}") ``` #### 3. 元数据一致性检查 确保Front Matter元数据一致性: ```python import frontmatter import yaml def check_metadata_consistency(markdown_files): metadata_fields = {} inconsistent_files = [] for file_path, content in markdown_files.items(): try: post = frontmatter.loads(content) if not hasattr(post, 'metadata'): inconsistent_files.append((file_path, "缺少Front Matter")) continue # 收集所有元数据字段 for key in post.metadata.keys(): metadata_fields.setdefault(key, 0) metadata_fields[key] += 1 except yaml.YAMLError: inconsistent_files.append((file_path, "YAML格式错误")) # 识别缺失关键字段的文件 required_fields = ['title', 'author', 'date'] for file_path, content in markdown_files.items(): post = frontmatter.loads(content) for field in required_fields: if field not in post.metadata: inconsistent_files.append((file_path, f"缺少必需字段: {field}")) return metadata_fields, inconsistent_files # 使用示例 metadata_stats, inconsistencies = check_metadata_consistency(analyzer.file_contents) print("元数据字段分布:", metadata_stats) print("不一致的文件:", inconsistencies) ``` ### 关键处理策略 1. **路径标准化** - 使用`pathlib`解决不同操作系统的路径差异 - 将相对路径转换为绝对路径,确保链接解析准确性 - 处理锚点链接和片段标识符(如`file.md#section`) 2. **内容规范化** - 统一日期格式(`YYYY-MM-DD`) - 标准化标题层级结构 ```python def standardize_headings(content): # 将H1替换为H2 content = re.sub(r'^# ', '## ', content, flags=re.MULTILINE) return content ``` 3. **HTML转换遗留处理** - 清理HTML标签残留: ```python def clean_html_tags(content): return re.sub(r'<[^>]+>', '', content) ``` - 转换HTML实体(如`&nbsp;`→空格) - 修复格式错误嵌套列表和代码块 4. **交叉引用增强** ```python def find_unlinked_references(content, keywords): missing_links = {} for keyword in keywords: if keyword in content and f"({keyword}.md)" not in content: missing_links[keyword] = content.count(keyword) return missing_links ``` ### 应用建议 1. **逐步整理流程**: 1. 建立关系图谱 2. 修复断链和元数据问题 3. 重构高耦合内容 4. 实现交叉引用自动化 2. **维护方案**: ```python # 自动更新工具 class MarkdownMaintainer: def __init__(self, directory): self.analyzer = MarkdownRelationshipAnalyzer(directory) self.analyzer.load_markdown_files() def weekly_update(self): self.analyzer.analyze_links() self.check_broken_links() self.verify_metadata() self.generate_report() ``` ### 工具整合建议 | 功能 | 推荐库 | 应用场景 | |------|--------|----------| | 内容解析 | `mistune` | 精确提取文档结构元素 | | 元数据处理 | `python-frontmatter` | 统一管理文档元数据 | | 图分析 | `networkx` | 可视化文件关系[^1] | | 文本处理 | `html2text` | 清理HTML残留标记[^2] | | 相似性分析 | `scikit-learn` | 检测内容冗余 | ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值