【问题标题】:Efficiently compare all combinations of two in a Scala collection有效地比较 Scala 集合中两者的所有组合
【发布时间】:2017-05-31 05:44:03
【问题描述】:

使用OpenFlow 我想计算有多少对流满足以下条件(给定任意两个流,例如f1f2):

  • f1Src ip 必须等于 f2Dst ip
  • f1Dst ip 必须等于 f2Src ip
  • f1f2 必须具有相同的协议。

我认为这将是两个元素(NFlows Choose 2) 的组合。感谢this question 我正在使用combinations 的方法,如下所示:

val pairFlows = matchs.combinations(2).filter{ list =>
  val f1 = list.head
  val f2 = list.tail.head

  f1.dl_type == f2.dl_type &&
  f1.nw_dst == f2.nw_src &&
  f1.nw_src == f2.nw_dst
}

我的问题是,这是执行此计算的最有效方式吗?还是创建一个HashMap 来跟踪每个srcdstprotocol type 会更好吗?

以下是数据示例:

{
    1: [
        {
            "actions": [
                "OUTPUT:2"
            ],
            "idle_timeout": 0,
            "cookie": 0,
            "packet_count": 18,
            "hard_timeout": 0,
            "byte_count": 1764,
            "duration_sec": 6884,
            "duration_nsec": 5000000,
            "priority": 1,
            "length": 120,
            "flags": 0,
            "table_id": 0,
            "match": {
                "dl_type": 2048,
                "dl_dst": "00:00:00:00:00:02",
                "nw_src": "10.0.0.1",
                "in_port": 1,
                "nw_dst": "10.0.0.2"
            }
        },
        {
            "actions": [
                "OUTPUT:2"
            ],
            "idle_timeout": 0,
            "cookie": 0,
            "packet_count": 18,
            "hard_timeout": 0,
            "byte_count": 1764,
            "duration_sec": 1123,
            "duration_nsec": 181000000,
            "priority": 1,
            "length": 120,
            "flags": 0,
            "table_id": 0,
            "match": {
                "dl_type": 2048,
                "dl_dst": "00:00:00:00:00:02",
                "nw_src": "10.0.0.3",
                "in_port": 3,
                "nw_dst": "10.0.0.2"
            }
        },
        {
            "actions": [
                "OUTPUT:1"
            ],
            "idle_timeout": 0,
            "cookie": 0,
            "packet_count": 10,
            "hard_timeout": 0,
            "byte_count": 980,
            "duration_sec": 1132,
            "duration_nsec": 253000000,
            "priority": 1,
            "length": 120,
            "flags": 0,
            "table_id": 0,
            "match": {
                "dl_type": 2048,
                "dl_dst": "00:00:00:00:00:01",
                "nw_src": "10.0.0.3",
                "in_port": 3,
                "nw_dst": "10.0.0.1"
            }
        },
        {
            "actions": [
                "OUTPUT:1"
            ],
            "idle_timeout": 0,
            "cookie": 0,
            "packet_count": 16,
            "hard_timeout": 0,
            "byte_count": 1568,
            "duration_sec": 1141,
            "duration_nsec": 652000000,
            "priority": 1,
            "length": 120,
            "flags": 0,
            "table_id": 0,
            "match": {
                "dl_type": 2048,
                "dl_dst": "00:00:00:00:00:01",
                "nw_src": "10.0.0.2",
                "in_port": 2,
                "nw_dst": "10.0.0.1"
            }
        },
        {
            "actions": [
                "OUTPUT:3"
            ],
            "idle_timeout": 0,
            "cookie": 0,
            "packet_count": 20,
            "hard_timeout": 0,
            "byte_count": 1960,
            "duration_sec": 6883,
            "duration_nsec": 961000000,
            "priority": 1,
            "length": 120,
            "flags": 0,
            "table_id": 0,
            "match": {
                "dl_type": 2048,
                "dl_dst": "00:00:00:00:00:03",
                "nw_src": "10.0.0.2",
                "in_port": 2,
                "nw_dst": "10.0.0.3"
            }
        },
        {
            "actions": [
                "OUTPUT:3"
            ],
            "idle_timeout": 0,
            "cookie": 0,
            "packet_count": 12,
            "hard_timeout": 0,
            "byte_count": 1176,
            "duration_sec": 6883,
            "duration_nsec": 984000000,
            "priority": 1,
            "length": 120,
            "flags": 0,
            "table_id": 0,
            "match": {
                "dl_type": 2048,
                "dl_dst": "00:00:00:00:00:03",
                "nw_src": "10.0.0.1",
                "in_port": 1,
                "nw_dst": "10.0.0.3"
            }
        },
        {
            "actions": [
                "OUTPUT:CONTROLLER"
            ],
            "idle_timeout": 0,
            "cookie": 0,
            "packet_count": 0,
            "hard_timeout": 0,
            "byte_count": 0,
            "duration_sec": 9156,
            "duration_nsec": 252000000,
            "priority": 65535,
            "length": 96,
            "flags": 0,
            "table_id": 0,
            "match": {
                "dl_type": 35020,
                "dl_dst": "01:80:c2:00:00:0e"
            }
        },
        {
            "actions": [
                "OUTPUT:CONTROLLER"
            ],
            "idle_timeout": 0,
            "cookie": 0,
            "packet_count": 22,
            "hard_timeout": 0,
            "byte_count": 1260,
            "duration_sec": 9156,
            "duration_nsec": 268000000,
            "priority": 0,
            "length": 80,
            "flags": 0,
            "table_id": 0,
            "match": {}
        }
    ],
}

这里有 8 个流,其中 3 个是对的。

【问题讨论】:

  • 从 groupBy(_.dl_type) 开始会给你几个较小的列表,而不是一个巨大的,以检查。根据您的数据的外观,这可能会有所帮助,有一点帮助或根本没有帮助。此外,从 n 个元素的列表中查看 2 个元素的所有组合是 O(n^2)。如果您保留两个列表,一个按 dst 排序,一个按 src 排序(这是在 O(nlogn) 中完成的),那么您可以遍历它们一次并收集所有匹配项。与上面的示例相比,这将为您提供更好的时间复杂度。
  • @Buhb 谢谢,我已经设法在O(n) 中编写了一个解决方案

标签: scala collections combinations openflow


【解决方案1】:

我终于把代码写成了O(n),我保留了一个Map,键为f.nw_src + f.nw_dst + f.dl_type,并赋值为Int,表示该键是否具有相应的对流(即键为@987654325的流) @. 这是最终代码:

val table =  flows./:(Map.empty[String,Int]){ case (m,f) =>
  val key = f.nw_src + f.nw_dst + f.dl_type
  val inverseKey = f.nw_dst + f.nw_src + f.dl_type
  val haspair = m get inverseKey match {
    case Some(v) => v + 1
    case None => 0
  }
  m + (key -> haspair)
}

val pairs = table.filter(_._2 > 0)

希望这对寻找类似问题的人有所帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-12-30
    • 1970-01-01
    • 1970-01-01
    • 2017-08-16
    • 2012-11-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多