从2D python列表中提取唯一元素并将它们放入新的2D列表中

时间:2016-03-01 02:26:34

标签: python list unique

现在我有一个包含三列和多行的2D列表,每列包含一种独特的东西。第一列是UserID,第二列是时间戳,第三列是URL。该列表如下所示:

[[304070, 2015:01:01, 'http:something1'],
[304070, 2015:01:02, 'http:something2'],
[304070, 2015:01:03, 'http:something2'],
[304070, 2015:01:03, 'http:something2'],
[304071, 2015:01:04, 'http:something2'],
[304071, 2015:01:05, 'http:something3'],
[304071, 2015:01:06, 'http:something3']]

如您所见,无论userID和时间戳如何,都有一些重复的URL。

我需要提取包含唯一URL的行并将它们放入新的2D列表中。

例如,无论userID和timestamp如何,第二行,第三行,第四行和第五行都具有相同的URL。我只需要第二行(第一行出现)并将其放入我的新2D列表中。话虽这么说,第一行有一个唯一的URL,我也会把它放到我的新列表中。最后两行(第六行和第七行)具有相同的URL,我只需要第六行。

因此,我的新列表应如下所示:

[304070, 2015:01:01, 'http:something1'],
[304070, 2015:01:02, 'http:something2'],
[304071, 2015:01:05, 'http:something3']]

我想过使用这样的东西:

for i in range(len(oldList):
    if oldList[i][2] not in newList:
        newList.append(oldList[i])

但显然这个不起作用,因为oldList[i][2]是一个元素,not in newList正在检查整个2D列表,即检查每一行。像这样的代码只会创建oldList的精确副本。

或者,我可以删除那些具有重复URL的行,因为在具有一百万行的2D列表上使用for循环加附加运算符确实需要一段时间。

4 个答案:

答案 0 :(得分:1)

解决这个问题的一个好方法是使用set。逐个浏览一个列表列表,如果该列表尚未存在,则将该URL添加到该列表中,并将包含该URL的完整列表添加到新列表中。如果URL已在集合中,则丢弃当前列表并移至下一个列表。

old_list = [[304070, "2015:01:01", 'http:something1'],
            [304070, "2015:01:02", 'http:something2'],
            [304070, "2015:01:03", 'http:something2'],
            [304070, "2015:01:03", 'http:something2'],
            [304071, "2015:01:04", 'http:something2'],
            [304071, "2015:01:05", 'http:something3'],
            [304071, "2015:01:06", 'http:something3']]
new_list = []
url_set = set()

for item in old_list:
    if item[2] not in url_set:
        url_set.add(item[2])
        new_list.append(item)
    else:
        pass

>>> print(new_list)
[[304070, '2015:01:01', 'http:something1'], [304070, '2015:01:02', 'http:something2'], [304071, '2015:01:05', 'http:something3']]

答案 1 :(得分:1)

>>> old_list = [[304070, "2015:01:01", 'http:something1'],
...            [304070, "2015:01:02", 'http:something2'],
...            [304070, "2015:01:03", 'http:something2'],
...            [304070, "2015:01:03", 'http:something2'],
...            [304071, "2015:01:04", 'http:something2'],
...            [304071, "2015:01:05", 'http:something3'],
...            [304071, "2015:01:06", 'http:something3']]
>>> temp_dict = {}
>>> for element in old_list:
...     if element[2] not in temp_dict:
...         temp_dict[element[2]] = [element[0], element[1], element[2]]
... 
>>> temp_dict.values()
[[304070, '2015:01:01', [304070, '2015:01:02', 'http:something2'], 'http:something1'], [304071, '2015:01:05', 'http:something3']]

注意:我假设列表中不同网址的顺序并不重要。如果确实重要,请使用OrderedDict代替默认dict

答案 2 :(得分:0)

您需要创建一个函数,使用url在列表中搜索项目。

def hasUrl(list, url):
    for item in list:
        if item[1] == url:
            return True
    return False

然后你的新列表创建算法应如下所示。

for i in range(len(oldList)):
    if not hasUrl(newList, oldList[i][2]): # check if url is in list
        newList.append(oldList[i])

此外,无需创建范围。 Python for循环按值迭代,因此您只需编写

for item in oldList:
    if not hasUrl(newList, item[2]): # check if url is not in list
        newList.append(item)

答案 3 :(得分:0)

my_list = [[304070, '2015:01:01', 'http:something1'],
           [304070, '2015:01:02', 'http:something2'],
           [304070, '2015:01:03', 'http:something2'],
           [304070, '2015:01:03', 'http:something2'],
           [304071, '2015:01:04', 'http:something2'],
           [304071, '2015:01:05', 'http:something3'],
           [304071, '2015:01:06', 'http:something3']]

从原始列表中提取所有网址。从此列表创建一个集合,为URL生成唯一值。使用列表推导来遍历此集合,并在生成的网址列表(index)上使用urls来找到该网址的第一个匹配项。

最后,使用另一个列表推导与enumerate一起选择具有匹配索引值的行。

urls = [row[2] for row in my_list]
urls_unique = set(urls)
idx = [urls.index(url) for url in urls_unique]
my_shorter_list = [row for n, row in enumerate(my_list) if n in idx]

>>> my_shorter_list
[[304070, '2015:01:01', 'http:something1'],
 [304070, '2015:01:02', 'http:something2'],
 [304071, '2015:01:05', 'http:something3']]