Warning: Cannot use a scalar value as an array in /home/admin/public_html/forum/include/fm.class.php on line 757

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/include/fm.class.php on line 770

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/topic.php on line 737
Форумы портала PHP.SU :: Как удалять из много мерного массива элменты по условию

 PHP.SU

Программирование на PHP, MySQL и другие веб-технологии
PHP.SU Портал     На главную страницу форума Главная     Помощь Помощь     Поиск Поиск     Поиск Яндекс Поиск Яндекс     Вакансии  Пользователи Пользователи


 Страниц (1): [1]   

> Без описания
bkmz1984
Отправлено: 14 Июля, 2016 - 22:56:12
Post Id



Новичок


Покинул форум
Сообщений всего: 14
Дата рег-ции: Июль 2016  
Откуда: г. Сумы, Украина


Помог: 0 раз(а)




Есть таблица в mysql.
Она имеет если упрощенно такой вид:
-------------------
| callid | status |
-------------------
| 1 | an |
-------------------
| 1 | an |
-------------------
| 1 | no an |
-------------------
| 2 | an |
-------------------
| 2 | no an |
-------------------
| 3 | no an |
-------------------

Я получаю из него 1000 записей. Как исключить из результата все записи со имеющее в status "no an" если была хоть одна запись с таким же callid но со status "an"

Я решил приблизительно так: Но чувствую решил я или неправильно или не оптимально или и то и другое

PHP:
скопировать код в буфер обмена
  1. <?PHP
  2.  
  3. // Данные для отладки
  4. // Боюсь что данные из mysql формируются не так само как тут:
  5. $data[0] = array("agent"=>"a1", "disposition"=>"ANSWERED", "callid"=>"12");
  6. $data[1] = array("agent"=>"a2", "disposition"=>"NO ANSWER", "callid"=>"12");
  7. $data[2] = array("agent"=>"a3", "disposition"=>"NO ANSWER", "callid"=>"12");
  8. $data[3] = array("agent"=>"a4", "disposition"=>"NO ANSWER", "callid"=>"13");
  9. $data[4] = array("agent"=>"a5", "disposition"=>"ANSWERED", "callid"=>"13");
  10. $data[5] = array("agent"=>"a6", "disposition"=>"BUSY", "callid"=>"13");
  11. $data[6] = array("agent"=>"a7", "disposition"=>"NO ANSWER", "callid"=>"14");
  12.  
  13.  
  14.  
  15. // Отладка
  16. print ("<pre>");        
  17. print_r($data);
  18. print ("</pre>");
  19.  
  20. $for_del = array();
  21.  
  22. for ($i = 0; $i < count($data); $i++) {
  23.     if ($data[$i]['disposition'] == "ANSWERED") {
  24.         for ($j = 0; $j < count($data); $j++) {
  25.             if ($data[$j]['callid'] == $data[$i]['callid'] AND $data[$j]['disposition'] == "NO ANSWER") {
  26.                 $for_del[] = $j;  
  27.             }
  28.         }
  29.     }
  30. }
  31.  
  32. foreach ($for_del as $key => $value){
  33.    unset($data[$value]);
  34. }
  35.  
  36. // Отладка
  37. print ("<pre>");        
  38. print_r($data);
  39. print ("</pre>");
  40.  
  41. echo json_encode($data);
  42.  
  43. ?>
 
My status
 Top
Мелкий Супермодератор
Отправлено: 15 Июля, 2016 - 11:10:40
Post Id



Активный участник


Покинул форум
Сообщений всего: 11926
Дата рег-ции: Июль 2009  
Откуда: Россия, Санкт-Петербург


Помог: 618 раз(а)




PHP:
скопировать код в буфер обмена
  1. $data[0] = array("agent"=>"a1", "disposition"=>"ANSWERED", "callid"=>"12");
  2. $data[1] = array("agent"=>"a2", "disposition"=>"NO ANSWER", "callid"=>"12");
  3. $data[2] = array("agent"=>"a3", "disposition"=>"NO ANSWER", "callid"=>"12");
  4. $data[3] = array("agent"=>"a4", "disposition"=>"NO ANSWER", "callid"=>"13");
  5. $data[4] = array("agent"=>"a5", "disposition"=>"ANSWERED", "callid"=>"13");
  6. $data[5] = array("agent"=>"a6", "disposition"=>"BUSY", "callid"=>"13");
  7. $data[6] = array("agent"=>"a7", "disposition"=>"NO ANSWER", "callid"=>"14");
  8.  
  9. $ans = [];
  10. foreach ($data as $row) {
  11.     if ($row['disposition'] == 'ANSWERED') {
  12.         $ans[ $row['callid'] ] = true;
  13.     }
  14. }
  15.  
  16. var_dump(array_filter($data, function ($row) use($ans) {
  17.     return ! ($row['disposition'] == 'NO ANSWER' and isset($ans[ $row['callid'] ]));
  18. }));


bkmz1984 пишет:
данные из mysql

Дайте show create table.
Эта задача элементарно решается на SQL.
(Добавление)
Как-то так:
CODE (SQL):
скопировать код в буфер обмена
  1. SELECT /**/ FROM tablename c WHERE disposition != 'NO ANSWER' OR NOT EXISTS(SELECT 1 FROM tablename ans WHERE ans.disposition = 'ANSWERED' AND ans.callid = c.callid);

CODE (SQL):
скопировать код в буфер обмена
  1. SELECT /**/ FROM tablename c WHERE c.disposition != 'NO ANSWER' OR c.callid NOT IN (SELECT ans.callid FROM tablename ans WHERE ans.disposition = 'ANSWERED');

CODE (SQL):
скопировать код в буфер обмена
  1. SELECT /**/ FROM tablename c LEFT JOIN (
  2.     SELECT DISTINCT ans.callid FROM tablename ans WHERE ans.disposition = 'ANSWERED'
  3. ) ans USING(callid)
  4. WHERE c.disposition != 'NO ANSWER' OR ans.callid IS NULL;

Любой из вариантов, какой производительнее - зависит от используемой версии субд. И лучше проверить все 3 и выбрать лучший под свою базу.


-----
PostgreSQL DBA
 
 Top
bkmz1984
Отправлено: 15 Июля, 2016 - 11:42:30
Post Id



Новичок


Покинул форум
Сообщений всего: 14
Дата рег-ции: Июль 2016  
Откуда: г. Сумы, Украина


Помог: 0 раз(а)




Мелкий пишет:

Дайте show create table.


Это подойдет ?

PHP:
скопировать код в буфер обмена
  1. (
  2.     [0] => Array
  3.         (
  4.             [disposition] => ANSWERED
  5.             [callid] => 150729
  6.             [agent] => a0
  7.         )
  8.  
  9.     [1] => Array
  10.         (
  11.             [disposition] => ANSWERED
  12.             [callid] => 150729
  13.             [agent] => a1
  14.         )
  15.  
  16.     [2] => Array
  17.         (
  18.             [disposition] => NO ANSWER
  19.             [callid] => 170000
  20.             [agent] => a2
  21.         )
  22.     [3] => Array
  23.         (
  24.             [disposition] => ANSWERED
  25.             [callid] => 170000
  26.             [agent] => a3
  27.         )
  28.     [4] => Array
  29.         (
  30.             [disposition] => NO ANSWER
  31.             [callid] => 179999
  32.             [agent] => a4
  33.         )
  34. )

(Добавление)
Спасибо. Теперь буду разбираться что тут написано

(Отредактировано автором: 15 Июля, 2016 - 11:43:25)

 
My status
 Top
bkmz1984
Отправлено: 15 Июля, 2016 - 14:18:47
Post Id



Новичок


Покинул форум
Сообщений всего: 14
Дата рег-ции: Июль 2016  
Откуда: г. Сумы, Украина


Помог: 0 раз(а)




Забыл акцентировать внимание на том, что те записи для у которых есть "NO ANSWER" и нет записи с таким же callid со статусом АNSWERED должны выводиться?
 
My status
 Top
bkmz1984
Отправлено: 15 Июля, 2016 - 16:27:05
Post Id



Новичок


Покинул форум
Сообщений всего: 14
Дата рег-ции: Июль 2016  
Откуда: г. Сумы, Украина


Помог: 0 раз(а)




Код ОЧЕНЬ интересный но можно его разжевать комментариями? Где что делается?
(Добавление)
Я не понял эту конструкцию:

PHP:
скопировать код в буфер обмена
  1. var_dump(array_filter($data, function ($row) use($ans) {
  2.     return ! ($row['disposition'] == 'NO ANSWER' and isset($ans[ $row['callid'] ]));
  3. }));
 
My status
 Top
Мелкий Супермодератор
Отправлено: 15 Июля, 2016 - 16:36:46
Post Id



Активный участник


Покинул форум
Сообщений всего: 11926
Дата рег-ции: Июль 2009  
Откуда: Россия, Санкт-Петербург


Помог: 618 раз(а)




bkmz1984 пишет:
что те записи для у которых есть "NO ANSWER" и нет записи с таким же callid со статусом АNSWERED должны выводиться

Нет, не забыли. Это учтено, потому и так сложно относительно тупого и быстрого фильтра disposition != 'NO ANSWER'

Смысл кода - строим индекс, включающий callid всех ANSWERED. callid в ключе массива для быстрого поиска. Значение массива нас при этом, в общем-то, не интересует никак. Я присвоил true, можно присвоить что угодно другое, кроме NULL - с null проверка через isset работать корректно не будет.
Затем отфильтровываем через штатный array_filter и замыкание все записи, у которых 'disposition' == 'NO ANSWER' и которые есть индексе, построенном ранее. Без потери смысла array_filter с замыканием можно заменить примерно таким foreach:
PHP:
скопировать код в буфер обмена
  1. $result = [];
  2. foreach ($data as $row) {
  3.     if ($row['disposition'] == 'NO ANSWER' and isset($ans[ $row['callid'] ]) {
  4.         continue;
  5.     }
  6.     $result[] = $row;
  7. }


-----
PostgreSQL DBA
 
 Top
bkmz1984
Отправлено: 15 Июля, 2016 - 16:51:03
Post Id



Новичок


Покинул форум
Сообщений всего: 14
Дата рег-ции: Июль 2016  
Откуда: г. Сумы, Украина


Помог: 0 раз(а)




МАГИЯ

PHP:
скопировать код в буфер обмена
  1.    
  2.  
  3. $data[0] = array("agent"=>"a1", "disposition"=>"ANSWERED", "callid"=>"12");
  4. $data[1] = array("agent"=>"a2", "disposition"=>"NO ANSWER", "callid"=>"12");
  5. $data[2] = array("agent"=>"a3", "disposition"=>"NO ANSWER", "callid"=>"12");
  6. $data[3] = array("agent"=>"a4", "disposition"=>"NO ANSWER", "callid"=>"13");
  7. $data[4] = array("agent"=>"a5", "disposition"=>"ANSWERED", "callid"=>"13");
  8. $data[5] = array("agent"=>"a6", "disposition"=>"BUSY", "callid"=>"13");
  9. $data[6] = array("agent"=>"a7", "disposition"=>"NO ANSWER", "callid"=>"14");
  10.          
  11. $callid_with_answered = array();
  12. foreach ($data as $row) {
  13.    if ($row['disposition'] == 'ANSWERED') {
  14.         $callid_with_answered[$row['callid']] = true;
  15.    }
  16. }
  17.    
  18. print ("<pre>");        
  19. print_r($data);
  20. print ("</pre>");
  21.        
  22. print ("<pre>");        
  23. print_r($callid_with_answered);
  24. print ("</pre>");
  25.        
  26. print ("<pre>");
  27. print_r(array_filter($data, function ($row) use($callid_with_answered) {
  28.         return !($row['disposition'] == 'NO ANSWER' and isset($callid_with_answered[ $row['callid'] ]));
  29. }));
  30. print ("</pre>");
  31.        
  32.        
  33.        
 
My status
 Top
bkmz1984
Отправлено: 18 Июля, 2016 - 16:42:24
Post Id



Новичок


Покинул форум
Сообщений всего: 14
Дата рег-ции: Июль 2016  
Откуда: г. Сумы, Украина


Помог: 0 раз(а)




Остановился на варианте:

PHP:
скопировать код в буфер обмена
  1. $callid_with_answered = array();
  2. foreach ($data as $row) {
  3.    if ($row['disposition'] == 'ANSWERED') {
  4.         $callid_with_answered[$row['callid']] = true;
  5.    }
  6. }
  7.  
  8. echo json_encode(array_filter($data, function ($row) use($callid_with_answered) {
  9.         return !(($row['disposition'] == 'NO ANSWER') and isset($callid_with_answered[$row['callid']]));
  10. }));


А можно еще как-то выкинуть все NO ANSWER кроме того у которого будет присутствовать самое раннее время звонка?
 
My status
 Top
bkmz1984
Отправлено: 19 Июля, 2016 - 13:46:38
Post Id



Новичок


Покинул форум
Сообщений всего: 14
Дата рег-ции: Июль 2016  
Откуда: г. Сумы, Украина


Помог: 0 раз(а)




Оптимально ли сделать так?

PHP:
скопировать код в буфер обмена
  1. //  Массив в котором указываются все callid всех записей
  2. $all_callid = array();
  3. foreach ($data_result as $row) {
  4.     $all_callid[] = $row['callid'];
  5. }
  6.  
  7. // Функция для сортировки
  8. function sort_p($a, $b){
  9.     return strcmp($a["data"], $b["data"]);
  10. }
  11.  
  12. $data_end = array();
  13. // Перебираем все полученные индификаторы предварительно исключив повторяющиеся функцией array_unique()
  14. foreach (array_unique($all_callid) as $key => $value) {
  15.    
  16.     // Создаемм массивы сгруппированные по callid
  17.     $qw = array_filter($data_result, function ($row) use ($value) {
  18.         return ($row['callid'] == $value);
  19.     });
  20.    
  21.     // Сортируем массив по возрастанию даты используя функцию "sort_p"
  22.     uasort($qw, "sort_p");
  23.    
  24.     // Берем только первый элемент массива
  25.     $data_end[] = array_shift($qw);
  26.  
  27. }
  28.  
  29.  

(Отредактировано автором: 19 Июля, 2016 - 13:48:56)

 
My status
 Top
Страниц (1): [1]
Сейчас эту тему просматривают: 0 (гостей: 0, зарегистрированных: 0)
« Вопросы новичков »


Все гости форума могут просматривать этот раздел.
Только зарегистрированные пользователи могут создавать новые темы в этом разделе.
Только зарегистрированные пользователи могут отвечать на сообщения в этом разделе.
 



Powered by PHP  Powered By MySQL  Powered by Nginx  Valid CSS  RSS

 
Powered by ExBB FM 1.0 RC1. InvisionExBB