从成对列表中提取包的有效算法是什么?

发布于 2024-09-28 09:08:07 字数 334 浏览 10 评论 0原文

我有一个对象对的列表。对象可以以任一顺序出现在对中。查找相同对象之间的所有对的包(即允许重复的集合)的最有效算法(和实现?)是什么。出于我的目的,对象引用可以被假定为指针、名称或一些类似的方便、简短、有用的表示。各个对是可识别的。不存在在该对的两个部分中具有相同对象的对。

因此,给定一个对列表(Oid 是一个对象引用;Pid 是一个对引用)

O1-P1-O2
O3-P2-O4
O5-P3-O1
O1-P4-O2
O2-P5-O1
O1-P6-O5
O7-P7-O8

应该返回:

P1;P4;P5 and P3;P6

I have a list of pairs of objects. Objects can appear in the pair in either order. What is the most efficient algorithm (and implementation?) to find all bags (ie sets with duplicates permitted) of pairs between the same objects. For my purpose the object references can be assumed to be pointers, or names or some similar convenient, short, useful representation. The individual pairs are identifiable. There are no pairs which have the same object in both parts of the pair.

So given a list of pairs (Oid is an object reference; Pid a pair reference)

O1-P1-O2
O3-P2-O4
O5-P3-O1
O1-P4-O2
O2-P5-O1
O1-P6-O5
O7-P7-O8

should return:

P1;P4;P5 and P3;P6

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

苏佲洛 2024-10-05 09:08:07

花哨的术语可能会让这个问题看起来很困难,但实际上非常简单。

  1. 对每对中的元素进行排序。 (既然你说对象可以表示为数字,那么我们就假设总是pair.first <=pair.second
  2. 对列表进行排序,使用传统的方式来比较对。即pair1 < pair2 表示pair1.first < pair2.firstpair1.first ==pair2.first &&对1.第二个<对2.第二个

示例中的排序列表将如下所示

O1-P1-O2
O1-P4-O2
O1-P5-O2
O1-P3-O5
O1-P6-O5
O3-P2-O4
O7-P7-O8

现在,一个“包”中的所有元素将占据列表中的连续位置。去抓住他们吧。

也有一些选项可以使用哈希来解决这个问题。

Fancy terminology may make this problem look difficult, but it's actually pretty simple.

  1. Order elements in each pair. (Since you said objects can be represented as numbers, let's assume pair.first <= pair.second always)
  2. Sort list, using traditional way to compare pairs. I.e. pair1 < pair2 means pair1.first < pair2.first or pair1.first == pair2.first && pair1.second < pair2.second.

Sorted list from your example will look like this

O1-P1-O2
O1-P4-O2
O1-P5-O2
O1-P3-O5
O1-P6-O5
O3-P2-O4
O7-P7-O8

Now all elements from one 'bag' will occupy consecutive spots in the list. Go ahead and grab them.

There're options to solve this with hash too.

ι不睡觉的鱼゛ 2024-10-05 09:08:07

您的对象上定义了“小于”吗?
如果是这样,那么您可以通过一次遍历配对列表来完成此操作。

1) 创建一个空的袋子集合,由两个“对象”参数索引。按照约定,第一个索引参数应小于第二个索引参数。

2) 循环遍历列表,并在 min(pair.left,pair.right), max(pair.left,pair.right) 处找到适当的包索引。将元素添加到该包中。

Is "less than" defined on your objects?
If so, then you can do this with a single pass through your list of pairs.

1) Create an empty collection of bags, indexed by two "object" parameters. By convention, the first index parameter should be less than the second index parameter.

2) Loop through the list, and find the appropriate bag index at min(pair.left,pair.right), max(pair.left, pair.right). Add the element to that bag.

软糖 2024-10-05 09:08:07

@Nikita Rybak 的解决方案 在 Python 中使用 itertools.groupby()

#!/usr/bin/env python
from itertools import groupby

pairs = """
O1-P1-O2
O3-P2-O4
O5-P3-O1
O1-P4-O2
O2-P5-O1
O1-P6-O5
O7-P7-O8
""".split()

def lex_order(pair):
    """'O2-P5-O1' -> ['01', '02']"""
    return sorted(pair.split('-')[::2])

data = sorted(pairs, key=lex_order)
for key, group in groupby(data, key=lex_order):
    print "key=%(key)s, pairs=%(pairs)s" % dict(key=key, pairs=list(group))

输出:

key=['O1', 'O2'], pairs=['O1-P1-O2', 'O1-P4-O2', 'O2-P5-O1']
key=['O1', 'O5'], pairs=['O5-P3-O1', 'O1-P6-O5']
key=['O3', 'O4'], pairs=['O3-P2-O4']
key=['O7', 'O8'], pairs=['O7-P7-O8']

@mbeckish的解决方案 在 Python 中:

#!/usr/bin/env python
from collections import defaultdict

pairs = """
O1-P1-O2
O3-P2-O4
O5-P3-O1
O1-P4-O2
O2-P5-O1
O1-P6-O5
O7-P7-O8
""".split()

bags = defaultdict(list)
for pair in pairs:
    i, _, j = pair.split('-') # 'O2-P5-O1' -> ['02', 'P5', '01']
    bags[min(i,j), max(i,j)].append(pair)

import pprint;
pprint.pprint(dict(bags))

输出:

{('O1', 'O2'): ['O1-P1-O2', 'O1-P4-O2', 'O2-P5-O1'],
 ('O1', 'O5'): ['O5-P3-O1', 'O1-P6-O5'],
 ('O3', 'O4'): ['O3-P2-O4'],
 ('O7', 'O8'): ['O7-P7-O8']}

@Nikita Rybak's solution in Python using itertools.groupby():

#!/usr/bin/env python
from itertools import groupby

pairs = """
O1-P1-O2
O3-P2-O4
O5-P3-O1
O1-P4-O2
O2-P5-O1
O1-P6-O5
O7-P7-O8
""".split()

def lex_order(pair):
    """'O2-P5-O1' -> ['01', '02']"""
    return sorted(pair.split('-')[::2])

data = sorted(pairs, key=lex_order)
for key, group in groupby(data, key=lex_order):
    print "key=%(key)s, pairs=%(pairs)s" % dict(key=key, pairs=list(group))

Output:

key=['O1', 'O2'], pairs=['O1-P1-O2', 'O1-P4-O2', 'O2-P5-O1']
key=['O1', 'O5'], pairs=['O5-P3-O1', 'O1-P6-O5']
key=['O3', 'O4'], pairs=['O3-P2-O4']
key=['O7', 'O8'], pairs=['O7-P7-O8']

@mbeckish's solution in Python:

#!/usr/bin/env python
from collections import defaultdict

pairs = """
O1-P1-O2
O3-P2-O4
O5-P3-O1
O1-P4-O2
O2-P5-O1
O1-P6-O5
O7-P7-O8
""".split()

bags = defaultdict(list)
for pair in pairs:
    i, _, j = pair.split('-') # 'O2-P5-O1' -> ['02', 'P5', '01']
    bags[min(i,j), max(i,j)].append(pair)

import pprint;
pprint.pprint(dict(bags))

Output:

{('O1', 'O2'): ['O1-P1-O2', 'O1-P4-O2', 'O2-P5-O1'],
 ('O1', 'O5'): ['O5-P3-O1', 'O1-P6-O5'],
 ('O3', 'O4'): ['O3-P2-O4'],
 ('O7', 'O8'): ['O7-P7-O8']}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文