使用Python,如何只将不同的消息添加到列表中?

时间:2014-07-22 07:27:38

标签: python regex

认证的Python Noob。请耐心等待。

在一百万(左右)文本行的多个文件中,我将过滤掉不同的文本。也就是说,即使数百万只包含15条不同的行,代码也应返回15行。

从文件中读取行,如果它不存在则将其放在列表中,将列表输出到另一个文件。听起来很简单?

虽然有一件小事:

我正在寻找消息,而不是字符串/子字符串,或者你有什么。我将在下面解释。

问题:

假设文件中有以下行:

  • 随机2345
  • Hello World
  • 您的代码是91939
  • 您的代码是54879
  • 您的代码是79865
  • Pancakes 2451
  • 您的验证码为123456
  • 您的验证码为789101

实际上,我应该做一个简单的if line doesn't exist in myList, add line to myList,它仍会返回重复项。输出应为:

  • 随机2345
  • Hello World
  • 您的代码是91939
  • Pancakes 2451
  • 您的验证码为123456

我要尝试的内容:

现在,这些数字并不重要,所以我可以通过简单地使用正则表达式或其他东西来寻找行中的所有数字,替换它们,然后将其与列表进行比较(这也删除了所有数字。)

原油,但这是我能想到的最简单的。

还在我身边吗?

更多问题:

现在来了困难的部分。除了上面的列表,我们还有以下内容:

  • 嗨,我的名字是兰斯。很高兴见到你。
  • 嗨,我的名字是珍妮。很高兴见到你。
  • 哟,dawg。姓名是John Erik。不要碰我的薯条。
  • 哟,dawg。姓詹姆斯。不要碰我的薯条。
  • 我喜欢海龟53669
  • Stefan评论了你的视频。
  • n00bpwn3rz对您的视频发表了评论。
  • RJ想和你谈谈。
  • Jenny喜欢你的照片。
  • Pi想跟你说话。
  • Pi说访问我的网站www.google.com
  • John Erik说访问我的网站www.johniscool.com
  • 詹姆斯做了水果冰块。

输出应该如下:

  • 嗨,我的名字是兰斯。很高兴见到你。
  • 哟,dawg。姓名是John Erik。不要碰我的薯条。
  • 我喜欢海龟53669
  • Stefan评论了你的视频。
  • RJ想和你谈谈。
  • Jenny喜欢你的照片。
  • Pi说访问我的网站www.google.com
  • 詹姆斯做了水果冰块。

我的大脑疼。我不仅需要将名称作为变量,我还必须注意网站。

现在,假设我将该行解剖为Chars,循环 - 将其与列表中的项目进行比较 - 也解析为Chars - 如果它遇到X个正数(来自行的Char =来自list_item的Char),我不会将其添加到列表中。这是否可行(如准确)?我如何在代码中执行此操作?也许是这样的事情?

line_char[] = line       #My Name is Jayson
list_char[] = list_item  #My Name is Lance

if (list_char[] contains some sequence of line_char[]):
     #My Name is Jayson = My Name is Lance (12 TRUE [My Name is ], 6 FALSE [Lance/Jayson]; 12 > 6)
     line exists in list
else:
     add line to list

还有其他想法吗?这可能更像是一个逻辑问题,但我想在Python中这样做,所以我只考虑其优点和局限性。

到目前为止的守则:

这里没什么可看的,伙计。

import os

in_path = "../aggregator/"
out_path = "../aggregator_output/"
# For server: for filename in os.listdir(in_path):
# For local: for filename in list_path:
list_path = os.listdir(in_path)
del list_path[0]
for filename in list_path:
    in_base, in_ext = os.path.splitext(filename)
    in_file = os.path.join(in_path, filename)
    out_file = os.path.join(out_path, in_base + "_cleaned.csv")
    print "Processing " + in_file
    print "Writing to " + out_file
    dirty_file = open(in_file, "rb").read().split("\n")
    clean_file = open(out_file "wb")
    list_unique = []
    for line in dirty_file:
        temp_line = re.sub('",', '^', line)
        delimited = temp_line.split(",")
        message = delimited[2]

到目前为止,我的所有代码仅仅是从文件中过滤出正确的行(第3列)。

我真的很感激这方面的一些帮助,因为这是一个相当有趣的问题,尽管我无法解决这个问题。

感谢。

P.S。 - 注释掉for-for-loop的部分代码是考虑到Mac上烦人的.DS-store废话隐藏文件,这会破坏其余的代码。我在Mac上进行测试,并在ubuntu服务器上进行实际操作。

3 个答案:

答案 0 :(得分:1)

从我看到的情况来看,你只想保留第一个不同的行,当有可能的"重复"你不在乎数字或名字的地方......

为什么不:

  • 查看该行的第一个单词,如果找到新的单词序列,则将其添加到列表中
  • 比较代表两行的两个字符串,并定义一个间隔,您知道两行不同。

例如,在这两行之间:

  • 嗨,我的名字是兰斯。很高兴见到你。
  • 嗨,我的名字是珍妮。很高兴见到你。

唯一的区别是Lance和Jenny。

然后,您可以根据行的所有字符的ASCII码总和的差异来编写比较函数(因为它不存在于Python中)。并且说:如果他们的"哈希"很接近。

以下是计算行哈希值的代码示例:

class myString(str):
  def __hash__(self):
    count = 0
    for c in self:
      count += ord(c)
    return count

a = myString('Hi, my name is Lance. Pleased to meet you.')
b = myString('Hi, my name is Jenny. Pleased to meet you.')
c = myString("Yo, dawg. Name's John Erik. Don't touch my fries.")

hash(a) = 3624
hash(b) = 3657
hash(c) = 4148

希望它会有所帮助!请注意,对于具有相同字符序列的句子,此解决方案可能会出现问题,例如:

hash(myString('abc')) = 294
hash(myString('bac')) = 294

答案 1 :(得分:1)

由于你正在处理英语句子,我想知道nltk是否可以用于此。它提供了一个可用于在句子中查找POS的词性(POS)标记器。那些具有相同标签序列的行是可能“相似”行(这也可以通过比较实际令牌来进一步改进)。

我试了一下你问题中的一些例句,看起来值得一试

import nltk

def pos_tags(text):
    return nltk.pos_tag(nltk.word_tokenize(text))

>>> pos_tags("Hi, my name is Lance. Pleased to meet you.")
[('Hi', 'NNP'),
(',', ','),
('my', 'PRP$'),
('name', 'NN'),
('is', 'VBZ'),
('Lance.', 'NNP'),
('Pleased', 'NNP'),
('to', 'TO'),
('meet', 'VB'),
('you', 'PRP'),
('.', '.')]

>>> pos_tags("Hi, my name is Jenny. Pleased to meet you")
[('Hi', 'NNP'),
(',', ','),
('my', 'PRP$'),
('name', 'NN'),
('is', 'VBZ'),
('Jenny.', 'NNP'),
('Pleased', 'NNP'),
('to', 'TO'),
('meet', 'VB'),
('you', 'PRP'),
('.', '.')]

然后可以将每个的POS标签编码为字符串并进行比较。如果它们相同,那么线很可能是相似的并且可以组合在一起。

>>> '-'.join([t[1] for t in pos_tags("Hi, my name is Jenny. Pleased to meet you")])
'NNP-,-PRP$-NN-VBZ-NNP-NNP-TO-VB-PRP-.'

>>> '-'.join([t[1] for t in pos_tags("Hi, my name is Lance. Pleased to meet you")])
'NNP-,-PRP$-NN-VBZ-NNP-NNP-TO-VB-PRP-.'

但我不确定它将如何在一百万行文本上表现。

答案 2 :(得分:1)

此方法使用集合并将其与所有已知集合进行比较。如果一半的单词在给定的集合中,则假定它们是相同的并跳过。

你必须明确定义何时句子相似,这样才能奏效。

a = """Hi, my name is Lance. Pleased to meet you.
Hi, my name is Jenny. Pleased to meet you.
Yo, dawg. Name's John Erik. Don't touch my fries.
Yo, dawg. Name's James. Don't touch my fries.
I like turtles 53669
Stefan commented on your video.
n00bpwn3rz commented on your video.
RJ wants to talk to you.
Jenny liked your photo.
Pi wants to talk to you.
Pi says visit my website at www.google.com
John Erik says visit my website at www.johniscool.com
James made fruity ice cubes."""


dirty_list = a.split('\n')
clean_list = [] # list of sets containing 'unique sets'
clean_list_pure = [] # list of the original sentences stored as sets in clean_list eg the output
for line in dirty_list:
    line_set = set(line.strip().split(' '))
    if all(len(line_set.intersection(clean_set)) < len(line_set)/2 for clean_set in clean_list):
        clean_list.append(line_set)
        clean_list_pure.append(line.strip())

for cl in clean_list_pure:
    print cl

作为输出,我们得到:

  你好,我的名字是兰斯。很高兴认识你。

     哟,哇,dawg。姓名约翰埃里克。别碰我的薯条。

     

我喜欢乌龟53669

     

Stefan评论了你的视频。

     

珍妮喜欢你的照片。

     

Pi说访问我的网站www.google.com

     詹姆斯做了水果冰块。