首页 > 解决方案 > 如何从函数构建地图

问题描述

我正在开发一个实现几个通用图形类型的库。我目前正在努力创建一种干净的实例化风格。

我的目标是创建这样的图表:

val graph = graphOf<Int>(true) {
            1 to setOf(2,3,4,)
            2 to setOf(1,3,4,)
            3 to emptySet<Int>()
            4 to emptySet<Int>()
        }

这将创建一个具有 4 个顶点 (1 ... 4) 的图,其中 1 和 2 连接到所有其他顶点,而 3 和 4 不连接到任何顶点。我认为这将是最干净、最符合人体工程学的风格。但它并没有填充底层地图。我知道可以构建这样的地图,因为我以前在某个地方有过这种 DSL,但我正在努力弄清楚如何。

被调用的代码:

fun <Vertex> graphOf(
    isDirected: Boolean,
    vertexEdgeMap: MutableMap<Vertex, Set<Vertex>>.() -> Unit // I think the problem lies here?
) = graphOf(isDirected, mutableMapOf<Vertex, Set<Vertex>>().also(vertexEdgeMap))

fun <Vertex> graphOf(
    isDirected: Boolean,
    vertexEdgeMap: Map<Vertex, Set<Vertex>> = emptyMap()
): Graph<Vertex> = mutableGraphOf(isDirected, vertexEdgeMap)

fun <Vertex> mutableGraphOf(
    isDirected: Boolean,
    vertexEdgeMap: Map<Vertex, Set<Vertex>> = emptyMap()
): MutableGraph<Vertex> = MutableAdjacencyMapGraphImpl<Vertex>(isDirected)
    .apply {
        vertexEdgeMap.forEach { addVertex(it.key) }
        vertexEdgeMap.forEach {
            from -> from.value.forEach {
            to -> addEdge(from.key, to) }
        }
    }

有人有任何提示吗?

标签: dictionarykotlindsl

解决方案


以下将允许您以您提到的类似方式编写“graphOf”。
我重写了“to”函数infix fun T.to(that: Set<T>)
看看它是否有帮助。

class GraphBuilder<T> {
    val graph: MutableMap<T, Set<T>> = mutableMapOf()

    infix fun T.to(that: Set<T>): GraphBuilder<T> {
        val graphBuilder = this@GraphBuilder
        graphBuilder.graph.put(this, that)
        return graphBuilder
    }
}

fun <T> graphOf(pair: GraphBuilder<T>.() -> Unit): GraphBuilder<T> {
    val builder = GraphBuilder<T>()
    pair(builder)
    return builder
}

fun main() {
    val graph =
        graphOf<Int>() {
            1 to setOf(2, 3, 4)
            2 to setOf(1, 3, 4)
            3 to emptySet()
            4 to emptySet()
        }
}

推荐阅读