قم بإنشاء صفيف متعدد الأبعاد مع خوارزمية باستخدام البيانات في صفيف أحادي الأبعاد

StackOverflow https://stackoverflow.com/questions/1709729

سؤال

لدي مجموعة ذاتية الأبعاد من كائنات PHP. يحتوي كل كائن على خصمين، سمة واحدة هي معرف الكائن الفريد والآخر هو المعرف الفريد لكائن آخر في الصفيف الذي هو الوالد الخاص به. علي سبيل المثال:

array(3) {
  [0]=>
  object(stdClass)#1 (2) {
    ["ID"]=>
    int(1)
    ["parentID"]=>
    int(0)
  }
  [1]=>
  object(stdClass)#2 (2) {
    ["ID"]=>
    int(3)
    ["parentID"]=>
    int(2)
  }
  [2]=>
  object(stdClass)#3 (2) {
    ["ID"]=>
    int(2)
    ["parentID"]=>
    int(1)
  }
}

أحتاج إلى تحويل هذه الصفيف الأبعاد إلى صفيف متعدد الأبعاد. لقد اتخذت بعض الطعنات في هذا ولكن لا يمكنني العثور على طريقة لإنجازها دون وجود حلقة لكل مستوى من التعشيش. يجب أن تكون الخوارزمية قادرة على التكيف مع مستويات لا حصر لها من التعشيش. لقد حاولت استخدام بعض تقنيات العودية لكنني لم أحملها تماما.

لإضافة القليل من التعقيد، الكائنات الموجودة في الصفيف الذي أحصل عليه ليس دائما في ترتيب مثير. حاولت تكرار هذا في مثالي أعلاه؛ ستلاحظ أن الكائن مع معرف 3 يأتي في الصفيف قبل الكائن مع معرف 2. لذلك من المحتمل أن تكون من شأنها أن تكون خوارزمية الفرز المعنية أيضا.

من الناحية المثالية، فإن المثال أعلاه سيحول شيئا مثل هذا:

Array
(
    [0] => Array
        (
            [ID] => 1
            [parentID] => 0
            [0] => Array
                (
                    [ID] => 2
                    [parentID] => 1
                    [0] => Array
                        (
                            [ID] => 3
                            [parentID] => 2
                        )

                )

        )

)
هل كانت مفيدة؟

المحلول

جرب هذه الخوارزمية:

// sort objects by parentID
function cmpNodes($a, $b) {
    return $a->parentID - $b->parentID;
}
usort($objects, 'cmpNodes');

// define first node as root of tree
$tree = (array) array_shift($objects);
// lookup table for direct jumps
$idTable = array($tree['ID'] => &$tree);
foreach ($objects as $object) {
    $node = (array) $object;
    // test if parent node exists
    if (!isset($idTable[$node['parentID']])) {
        // Error: parent node does not exist
        break;
    }
    // append new node to the parent node
    $idTable[$node['parentID']][] = $node;
    // set a reference in the lookup table to the new node
    $idTable[$node['ID']] = &$idTable[$node['parentID']][count($idTable[$node['parentID']])-3];
}
// unset($idTable);
var_dump($tree);

لقد استخدمت طاولة بحث ($idtable) لمعرفات القفز مباشرة إلى العقد.

نصائح أخرى

لذلك، تماما مثل السلائف - أنا لا أعرف PHP، حقا على الإطلاق. أنا في المقام الأول مطور لغة نمط C (AKA C، الهدف C وجافا). لذلك قد يكون بعض هذا الأمر أكثر صعوبة في PHP، ولكن هذه هي المحاولة التي سأجعلها:

//the original input array
oldArray;
//the output array
array[] newArray = new array[];

foreach (element : oldArray) {
    //if the element is at the top, put it at the top of the array
    if (element.parentId == 0) {
        newArray.add(element);
    } else {
        //otherwise, find it's parent and put it in the child array of the parent
        for (potentialParent : oldArray) {
            if (potentialParent.id = element.parentId) {
                potentialParent.array.add(element);
                break;
            }
        }
    }
}

بضعة ملاحظات: أفترض أنك تمر كل شيء حول المؤشرات. إذا كنت تقوم بعمل نسخ من الكائنات، فمن الصعب، ولكن ليس مستحيلا. أنا أيضا افتراض أنك تستطيع تغيير حجم مجموعة ديناميكيا. مرة أخرى، أنا لست على علم PHP - إذا لم تتمكن من القيام بذلك، فستحتاج إلى طريقة إجرائية للقيام بهذا السلوك. في Java، أود استخدام نوع القائمة، أو مجرد نسخ الصفيف وإعادة تعيينه مرة أخرى.

مفتاح العمل في هذه الخوارزمية هو أن الأطفال يتم وضعهم تحت والديهم - أينما كانوا - في تمريرة واحدة. هذا يعني أنه، بغض النظر عن الأمر، سيتم إنشاء التسلسل الهرمي في هذا النجاح الفردي. إذا كنت بحاجة إلى مجموعة التفاف حول الوالد التي تظهر في مثالك، يمكنك ببساطة إضافة شيء من هذا القبيل إلى نهاية الرمز:

finalArray = new array[];
finalArray[0] = newArray;

أتمنى أن يساعدك هذا.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top