Переупорядочить элементы массива на основе нескольких критериев

1

Все, кого я попросил, заставили эту проблему слишком сложно, надеюсь, здесь есть кто-то, кто может справиться с этим.

У меня есть программа, которая генерирует визитные карточки с входами, предоставленными пользователем (имя, название, адрес и т.д.).

У меня также есть страница, на которой пользователи могут настроить способ отображения информации на карте: http://screencast.com/t/5j5CKAd0vi2l

Эти конфигурации используются так, что если некоторые поля пусты, то другие поля могут перемещаться, чтобы иметь место пустое поле.

Как мы должны ожидать, что он будет работать: когда проверяется "поле", это означает, что он может двигаться. Стрелка указывает позицию, в которой она должна двигаться. Например, имя должно двигаться вниз, а заголовок должен двигаться вверх. Поэтому, если во входном имени нет имени, и есть заголовок, заголовок загорится и займет пустое пространство имени.

Когда поле не проверяется, это означает, что он не может двигаться, и поле не может занять свое положение (или перешагнуть через него). Так, например, если есть имя, но нет названия, тогда имя будет спускаться, чтобы занять название, но не может идти дальше (даже если "Office tel" был пуст, поэтому будет пустое место на визитной карточке).

Используя тот же пример конфигурации, если пользователь не вводил мобильный и электронный адрес, а ввел последние 2 поля (адрес 1 и город, состояние, почтовый индекс), то эти последние 2 поля будут подниматься на 2 поля и занимать места мобильной и электронной почты.

Позвольте сказать, что мои визитные карточки:

(checked, pointing down) Name: Dan
(checked, pointing up) Title:
(unchecked) Office tel:
(checked, pointing up) Mobile tel:
(checked, pointing up) Email: [email protected]
(checked, pointing up) Address 1: 12 jal
(checked, pointing up) City, state, zip: NYC, NY, 12345

Полученный массив renderValues, который мне нужен, будет выглядеть так:

(
    [0] =>
    [1] => Dan
    [2] => 
    [3] => [email protected]
    [4] => 12 jal
    [5] => NYC, NY, 12345
    [6] =>  
)

Это не то, что я получаю с моим кодом. Возможно, вам это не понадобится, и это может смутить еще больше, но вот то, что я пробовал до сих пор:

foreach ($renderBlocksPropsByOrder as $blockID => $field) {
    $direction = $field['blankSensitivityDirection'];

    // note: if a field is not blank sensitive, it is locked

    if (trim($renderValues[$blockID]) == '' && $field['isBlankSensitive'] == '1') {
        // if ($renderBlocksPropsByOrder[$blockID + 1])
        // the field(s) around this field can take its position
        // ??? if the field above is pointing down and the field below is pointing up, give priority to the field down ???
    } else if (trim($renderValues[$blockID]) == '' && $field['isBlankSensitive'] == '0') {
        // fields above this field cannot go down past it even if it empty, but they can all go down until they reach it
        // fields below this field cannot go up past it even if it empty, but they can all go up until they reach it
        // this field will be a "blank" space field
    } else if (trim($renderValues[$blockID]) != '' && $field['isBlankSensitive'] == '0') {
        // similar as the above case, except this field won't be a blank space
    } else if (trim($renderValues[$blockID]) != '' && $field['isBlankSensitive'] == '1') {
        // this field should move if it can
        if ($direction === 'down') {
            // check fields below it to move it to the lowest available spot
            // (fields below have a higher index)
            for ($i = $blockID + 1; $i < $numBlocks; $i++) {
                if (trim($renderValues[$i]) != '') {
                    // prevent stepping over a field that has a value
                    break;
                }
                if (trim($renderValues[$i]) == '' && $renderBlocksPropsByOrder[$i]['isBlankSensitive'] == '1') {
                    $renderValues[$i] = $renderValues[$blockID];
                    $renderValues[$blockID] = ' ';
                    break;
                }
            }
        } else if ($direction === 'up') {
            // check fields above it to move it to the highest available spot
            // (fields above have a lower index)
            for ($i = $blockID - 1; $i >= 0; $i--) {
                if (trim($renderValues[$i]) != '') {
                    // prevent stepping over a field that has a value
                    break;
                }
                if (trim($renderValues[$i]) == '' && $renderBlocksPropsByOrder[$i]['isBlankSensitive'] == '1') {
                    $renderValues[$i] = $renderValues[$blockID];
                    $renderValues[$blockID] = ' ';
                    break;
                }
            }
        }
    }

}

Массив renderBlocksPropsByOrder имеет конфигурацию каждого поля:

(
[0] => Array
    (
        [blockID] => 0
        [isBlankSensitive] => 1
        [blankSensitivityDirection] => down
    )

[1] => Array
    (
        [blockID] => 1
        [isBlankSensitive] => 1
        [blankSensitivityDirection] => up
    )

[2] => Array
    (
        [blockID] => 2
        [isBlankSensitive] => 0
        [blankSensitivityDirection] => ''
    )

[3] => Array
    (
        [blockID] => 3
        [isBlankSensitive] => 1
        [blankSensitivityDirection] => up
    )

[4] => Array
    (
        [blockID] => 4
        [isBlankSensitive] => 1
        [blankSensitivityDirection] => up
    )

[5] => Array
    (
        [blockID] => 5
        [isBlankSensitive] => 1
        [blankSensitivityDirection] => up
    )

[6] => Array
    (
        [blockID] => 6
        [isBlankSensitive] => 1
        [blankSensitivityDirection] => up
    )

)

Значение RenderValues имеет значение для каждого поля. Первоначальный массив renderValues выглядит так:

(
    [0] => Dan
    [1] => 
    [2] => 
    [3] => 
    [4] => [email protected]
    [5] => 12 jal
    [6] => NYC, NY, 12345
)

Я проводил много времени на этом, действительно, любая помощь, которая может помочь мне продвинуться вперед, будет очень, очень оценена.

Если этот способ окажется слишком сложным, я сделаю все возможное для альтернативного, удобного для пользователя способа настройки визитных карточек.

  • 3
    Я явно не понимаю, что такое «двигаться вверх» или «двигаться вниз». Если, например, «заголовок» пуст, то все после него поднимается вверх (пространство «заголовок» удаляется) и все. Нет? Какая разница с тем, что вы хотите? Или есть какая-то конкретная причина, почему вы хотите оставить пустые места в вашем массиве?
  • 0
    Если заголовок не указан и имя есть, имя должно сместиться вниз, чтобы не было пробелов. Видать эту сгенерированную карту не так, согласно конфигурации: screencast.com/t/Lo98w9TzXvO2
Показать ещё 10 комментариев
Теги:
arrays
sorting

1 ответ

0
Лучший ответ

Я надеюсь, что он решает вашу проблему (нашел интересный случай и потратил часть утра на это)

EDIT: просто переделали функции и модели, поэтому они будут проходить так, как ожидалось, чтобы просматривать всю модель снова и снова, пока каждый слот не будет правильно отсортирован.

// Card Model
$card = array (
    1 => array(
        "label"=>"Name",
        "canmove"=>"down",
        "value"=>"Dan"
        ),
    2 => array(
        "label"=>"Title",
        "canmove"=>"up",
        "value"=>""
        ),
    3 => array(
        "label"=>"Office Tel",
        "canmove"=>"n",
        "value"=>""
        ),
    4 => array(
        "label"=>"Mobile Tel",
        "canmove"=>"up",
        "value"=>""
        ),
    5 => array(
        "label"=>"Email",
        "canmove"=>"up",
        "value"=>"[email protected]"
        ),
    6 => array(
        "label"=>"Address 1",
        "canmove"=>"up",
        "value"=>"12 jal"
        ),
    7 => array(
        "label"=>"City, State, Zip",
        "canmove"=>"up",
        "value"=>"NYC, NY, 12345"
        ),
);

// Render it!
$renderedCard = renderCard($card);

// Testing
foreach($renderedCard as $key=>$values) {
    echo "[".$key."] ".$values['label'].": ".$values['value']."<br>";
}

// Structural view
echo "<pre>";
print_r($renderedCard);
echo "</pre>";




// This function nullifies every slot with empty 'value', except if
// its 'canmove' is 'n', which may keep intact
function clearCard($card) {
    $newCard = array();
    foreach ($card as $slot=>$props) {
        $props['value'] != '' || $props['canmove'] == 'n' ?
            $newCard[$slot] = $card[$slot] :
            $newCard[$slot] = null;
    }
    return $newCard;
}

// This function will move each slot to occupy the empty ones, based
// on 'canmove' criteria
function renderCard($card) {
    $cleanCard = clearCard($card);
    $refactor = 0;
    // iterates over cleanCard to perform a 'bubble sort'
    while ($refactor < count($cleanCard)) {
        foreach ($cleanCard as $slot => $props) {
            switch ($props['canmove']) {
                // if 'up', and upward slot is empty,
                // occupy its place and null itself next
                case 'up':
                    // if it overflows the card array offset, breaks
                    if ($slot-1 <= 0) break;
                    // if upper 'value null, means it can be filled!
                    if ($cleanCard[$slot-1] == null) {
                        $cleanCard[$slot-1] = $cleanCard[$slot];
                        $cleanCard[$slot] = null;
                    }
                    break;
                // same as 'up', but checking downward field
                case 'down':
                    if ($slot+1 > count($cleanCard)) break;
                    if ($cleanCard[$slot+1] == null) {
                        $cleanCard[$slot+1] = $cleanCard[$slot];
                        $cleanCard[$slot] = null;
                    }
                    break;
            }
        }
        // increment the refactor to loop while over cleanCard count
        $refactor++;
    }
    // when finished, returns the rendered array
    return $cleanCard;
}

ВЫХОДЫ

1) Следуя модели на ваш вопрос:

[1] :
[2] Name: Dan
[3] Office Tel:
[4] Email: [email protected]
[5] Address 1: 12 jal
[6] City, State, Zip: NYC, NY, 12345
[7] : 

2) Добавление "Название" (CEO):

[1] Name: Dan
[2] Title: CEO
[3] Office Tel:
[4] Email: [email protected]
[5] Address 1: 12 jal
[6] City, State, Zip: NYC, NY, 12345
[7] : 

3) И теперь, "Мобильный телефон":

[1] Name: Dan
[2] Title: CEO
[3] Office Tel:
[4] Mobile Tel: 55559999
[5] Email: [email protected]
[6] Address 1: 12 jal
[7] City, State, Zip: NYC, NY, 12345

4) Что делать, если у вас есть "Название", но не "Имя"? Давайте посмотрим:

[1] Title: CEO
[2] :
[3] Office Tel:
[4] Email: [email protected]
[5] Address 1: 12 jal
[6] City, State, Zip: NYC, NY, 12345
[7] : 

5) Теперь удалите "Адрес 1", поэтому "Город, штат, почтовый индекс" должен занять свое место:

[1] Title: CEO
[2] :
[3] Office Tel:
[4] Email: [email protected]
[5] City, State, Zip: NYC, NY, 12345
[6] :
[7] :

6) [РЕДАКТИРОВАТЬ] Установка поля "Электронная почта" как canmove 'down', а также "Address 1" и "City, State, Zip" с пустыми значениями, поэтому Email должен двигаться полностью вниз ::

[1] Title: CEO
[2] :
[3] Office Tel:
[4] :
[5] :
[6] :
[7] Email: [email protected]

Не стесняйтесь выполнять другие тесты и давать обратную связь, я отлично провел время!

(Удалите прежний РЕДАКТР предыдущего ответа в отношении вопросов по индексу и уведомлениям, поскольку это не так)

  • 0
    Лучшее решение, чтобы избежать уведомлений - это не error_reporting(~E_NOTICE); , но исправляя уведомление. (Существуют здесь тестовые индексы.) Плюс «некоторые тесты, которые я сделал, не прошли» => Было бы хорошо сказать, какой из них, чтобы помочь OP. :)
  • 0
    Согласен, но, как я уже сказал, «не окончательное решение; может быть, хорошая отправная точка», что-то для работы. Он собирается внести изменения, поскольку его данные поступают через другую структуру массива. Как бы то ни было, неудачные тесты немного подтолкнули вверх, как вынуждая стек переключать элементы, когда все с нечетным индексом получали отказ canmove. Некоторые поля пропали без вести! Но я предполагаю, что это не будет так, поскольку эта ситуация не соответствует описанному сценарию.
Показать ещё 13 комментариев

Ещё вопросы

Сообщество Overcoder
Наверх
Меню