Итерация по вложенному списку для возврата внутреннего списка по указанному параметру - PullRequest
0 голосов
/ 22 ноября 2018

Цель - вернуть внутренний список объектов с заданным параметром из списка данных.Слой, на котором этот объект будет найден, может отличаться.

Псевдокод для объекта:

class Object {
   var id: Int
   var innerObjects: ArrayList<Object>
}  

Если параметр innerObjects равен нулю, мы достигли листа.

Нам даны ArrayList<Object>, которые являются данными, и id, которые мы ищем.Объект, который мы ищем, может находиться на любом уровне списка.

Теперь у меня есть этот фрагмент кода, но он проверяет только 2 уровня списка.Пожалуйста, предложите решение, которое будет работать для любого количества уровней в списке.Возможно с рекурсией.

private fun getObject(data: ArrayList<Object>, id: Int): ArrayList<Object> {
        var result = ArrayList<Object>()
        for (i in 0 until data.size) {
            if (data[i].id == id) {
                result = data[i].innerObjects
            } else {
                for (j in 0 until data[i].innerObjects.size) {
                    if (data[i].innerObjects[j].id == id) {
                        result = data[i].innerObjects[j].innerObjects
                    }
                }
            }
        }
        return result
    }

Кстати, код написан на Kotlin, но вы можете предложить решение на Kotlin или Java.

Ответы [ 3 ]

0 голосов
/ 22 ноября 2018

Я написал код Java для решения:

ArrayList<TreeNode> solve(TreeNode treeNode, int id) {
    if(treeNode == null) return null;
    if(treeNode.id == id) return treeNode.nodes;
    if(treeNode.nodes == null) return null;
    ArrayList<TreeNode> ans = null, temp = null;
    for(TreeNode t: treeNode.nodes) {
        temp = solve(t, id);
        if(temp != null) ans = temp;
    }
    return ans;
}

Демонстрация на Ideone: https://ideone.com/cMmAqD

0 голосов
/ 22 ноября 2018

Решение, которое я применил для своего дела в Котлине, для тех, кто заинтересован!

private fun getObjectById(item: Object, id: Int): ArrayList<Object>? {
    if (item.id == id) return item.innerObjects
    for (child in item.innerObjects) {
        val temp = getObjectById(child, id)
        if (temp!!.isNotEmpty()) return temp
    }
    return ArrayList()
}

fun combineLists(data: ArrayList<Object>?, id: Int) {
    for (j in 0 until data.size) {
         getObjectById(data[j], id)?.let {
            result.clear()
            result.addAll(it)
         }
    }
}
0 голосов
/ 22 ноября 2018

Итак, в этом случае использование базовой рекурсии решит эту проблему, но будьте осторожны, потому что этот вид поиска может быстро привести к буквальному StackOverflowException с.

fun getInnerObjectsById(nodes: ArrayList<Object>, id: Int) : ArrayList<Object>? {
    nodes.forEach{
        val ans = solve(it, id)
        if (ans != null) return ans
    }
    return null
}

fun getInnerObjectsById(obj: Object?, id: Int): ArrayList<Object>? {
    if (obj?.id == null || obj.innerObjects == null) return null
    if (obj.id == id) return obj.innerObjects
    return obj.innerObjects?.mapNotNull {
        solve(it, id)
    }?.firstOrNull()
}

Это более сложный, но обязательный поиск.

fun getInnerObjectsById(data: ArrayList<Object>, id: Int): ArrayList<Object>? {
    var activeList: List<Object> = data
    while (true) {
        val match = activeList.firstOrNull { it.id == id }
        if (match != null) return match.innerObjects
        activeList = activeList.flatMap { it.innerObjects ?: emptyList<Object>() }

        if (!activeList.isNotEmpty())
            return null
    }
}
...