【问题标题】:Classify array of strings based on commonalities根据共性对字符串数组进行分类
【发布时间】:2010-12-15 17:55:19
【问题描述】:

我有巨大的字符串列表(200000)(多字)。我想根据这些字符串之间的单词匹配的comman数组对这些字符串进行分组。我想不出一个低计算时间的算法

“AB 500”
“巴士 AB 500”
“新闻 CA”
"新闻 CA BLAH"

我的计划是
一种。将它们标记为单词。
湾。创建全局数组令牌
C。将这些字符串与常见标记进行比较。

正如您所猜测的那样,这无济于事。你能为此建议一个算法吗? 我正在用python写这个..

【问题讨论】:

  • 假设三个字符串“News CA”、“News What”、“News CA What”,它们是如何分组的?他们都是“新闻”组的一部分,然后还有子组?
  • 这有点未指定。如果输入还包括“Bus AB”、“Bus CD 500”和“Bus AB 201”怎么办?哪个组有什么?
  • 打算根据匹配的token数量和token长度进行评分

标签: python string algorithm classification


【解决方案1】:

200000不算多,你可以这样

  1. 拆分每个字符串以获取令牌 例如“新闻 CA BLAH”-> [“废话”、“CA”、“新闻”]
  2. 为每个列表长度创建一个字典条目,例如在 ["Blah", "CA", "News"] 的情况下,所有组合按顺序排列
  3. 现在只需遍历 dict 并查看组

示例代码:

data="""AB 500
Bus AB 500
News CA
News CA BLAH"""

def getCombinations(tokens):
    count = len(tokens)
    for L in range(1,count+1):
        for i in range(count-L+1):
            yield tuple(tokens[i:i+L])

groupDict = {}
for s in data.split("\n"):
    tokens = s.split()
    for groupKey in getCombinations(tokens):
        if groupKey not in groupDict:
            groupDict[groupKey] = [s]
        else:
            groupDict[groupKey].append(s)

for group, values in groupDict.iteritems():
    if len(values) > 1:
        print group, "->", values

它输出:

('News', 'CA') -> ['News CA', 'News CA BLAH']
('AB',) -> ['AB 500', 'Bus AB 500']
('500',) -> ['AB 500', 'Bus AB 500']
('CA',) -> ['News CA', 'News CA BLAH']
('AB', '500') -> ['AB 500', 'Bus AB 500']
('News',) -> ['News CA', 'News CA BLAH']

【讨论】:

    【解决方案2】:

    你的意思是这样的吗?

    >>> from collections import defaultdict
    >>> L=["AB 500",
    ... "Bus AB 500",
    ... "News CA",
    ... "News CA BLAH"]
    >>> d=defaultdict(list)
    >>> for s in L:
    ...     for w in s.split():
    ...         d[w].append(s)
    ... 
    >>> print d["News"]
    ['News CA', 'News CA BLAH']
    >>> print d["CA"]
    ['News CA', 'News CA BLAH']
    >>> print d["500"]
    ['AB 500', 'Bus AB 500']
    

    【讨论】:

      【解决方案3】:

      除非重复单词是您的用例的重要特征,否则我建议使用集合。即:

      thestrings = [
      "AB 500",
      "Bus AB 500",
      "News CA",
      "News CA BLAH",
      ]
      
      thesets = dict((s, set(s.split())) for s in thestrings)
      
      similarities = dict()
      for s in thestrings:
        for o in thestrings:
          if s>=o: continue
          sims = len(thesets[s] & thesets[o])
          if not sims: continue
          similarities[s, o] = sims
      
      for s, o in sorted(similarities, similarities.get, reverse=True):
        print "%-16r %-16r %2d" % (s, o, similarities[s, o])
      

      这与您要查找的内容接近吗?它确实以你想要的方式对你给出的 4 个字符串进行分类,但这是一个非常薄弱的​​样本,当然,所以我在仔细检查;-)。

      【讨论】:

      • 这将非常非常慢,正如 OP 所说的 200000 个字符串,意味着循环 4 万次
      • 是的,它是O(n**2),但如果它接近 OP 的要求,那么它就是优化算法和启发式优化的简单基础。目前的问题只是有点不确定;-)。
      【解决方案4】:

      如果将字符串“AB 500 News CA”添加到您的列表中会发生什么?两组字符串必须合并吗?如果不是,如何拆分字符串列表,为什么?

      这样的问题的一个非常通用的工作流程(如果我理解正确的话)是这样的:

      1. 通过倒排索引获取候选对列表/All pairs similarity search/Simhashing
      2. 为每对计算一些距离函数并将它们组合成一个权重
      3. 每个加权对((a, b), weight)现在代表图中的一条边,您可以通过层次聚类/幂迭代将其聚类到“单词匹配组”中

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多