2016-02-06 3 views
0

У меня есть массив объектов. За каждым gateType:entry должен следовать объект gateType:exit.создание массива, который содержит отсутствующие объекты

Проблема заключается в некотором объекте ввода, а некоторые объекты выхода отсутствуют/пропускаются. Мне нужно создать массив объектов с недостающими объектами.

  [{ 
       "dateTime": "2016-01-28 15:18:26", 
       "gateType": "entry", 
      }, { 
       "dateTime": "2016-01-28 15:18:27", 
       "gateType": "exit", 
      }, { 
       "dateTime": "2016-01-28 15:19:26", 
       "gateType": "entry", 
      }, { 
       "dateTime": "2016-01-28 15:19:27", 
       "gateType": "exit", 
      }, { 
       "dateTime": "2016-01-28 15:20:26", 
       "gateType": "entry", 
      }, 
// here is the exit object is missing for above 
      { 
       "dateTime": "2016-01-28 15:21:25", 
       "gateType": "entry", 
      }, { 
       "dateTime": "2016-01-28 15:21:26", 
       "gateType": "exit", 
      }, { 
       "dateTime": "2016-01-28 15:22:25", 
       "gateType": "entry", 
      }, { 
       "dateTime": "2016-01-28 15:22:26", 
       "gateType": "exit", 
      }, 
// here is the entry object is missing for below 
      { 
       "dateTime": "2016-01-28 15:23:26", 
       "gateType": "exit", 
      }] 

Каждый entry должно сопровождаться exit. Но, как вы видите, некоторые объекты ввода или выхода не существуют.

Раствор для вышеприведенного примера является:

  [{ 
       "dateTime": "2016-01-28 15:20:26", 
       "gateType": "exit", 
      },{ 
       "dateTime": "2016-01-28 15:23:26", 
       "gateType": "enty", 
      }] 

Мое решение было это, но он не работает, как я ожидал:

function detectMissingOnes(rows) { 

     var missings = []; 
     var current = null; 

     rows.forEach(function (key, index) { 


      if (index == 0) { 

       if(key.gateType == "exit"){ 


        var resultDate = moment(key.dateTime); 
        resultDate = resultDate.subtract(1, 'seconds').format("YYYY-MM-DD HH:mm:ss"); 

        missings.push({ 
         dateTime: resultDate, 
         gateNumber: key.gateNumber, 
         gateType: "entry", 
         personId: key.personId, 
         fix: 1 
        }); 

       } 

       current = key; 
       return true; 
      } 

      if (current.gateType == key.gateType) { 

       var type = key.gateType == "entry" ? "exit" : "entry"; 

       var resultDate = moment(current.dateTime); 
       if(type == "entry"){ 
        resultDate = resultDate.subtract(1, 'seconds').format("YYYY-MM-DD HH:mm:ss"); 
       }else { 
        resultDate = resultDate.add(1, 'seconds').format("YYYY-MM-DD HH:mm:ss"); 
       } 


       missings.push({ 
        dateTime: resultDate, 
        gateNumber: current.gateNumber, 
        gateType: type, 
        personId: current.personId, 
        fix: 1 
       }); 

      } 

      current = key; 

     }); 

     return missings; 
    } 

Не могли бы вы помочь мне написать алгоритм с или без lodash?

ответ

1

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

Я не пользовался какой-либо библиотекой, поэтому даже манипуляции с секундами выполняются с помощью стандартных функций JavaScript, которые делают это немного дольше.

Этот живой фрагмент позволяет ввести входной массив (JSON) и получить результат функции (также JSON).

// main algorithm: 
 
function detectMissingOnes(rows) { 
 
    var collect = rows.reduce(function (collect, curr) { 
 
     var expectedMove = collect.openEntry ? "exit" : "entry"; 
 
     var expectedPerson = collect.openEntry ? collect.openEntry.personId : curr.personId; 
 
     console.log('expected move: ', expectedMove, ' person: ', expectedPerson); 
 
     console.log('current move: ', curr.gateType, ' person:', curr.personId); 
 
     if (expectedMove == curr.gateType && 
 
       expectedPerson == curr.personId) { 
 
      console.log('ok'); 
 
      // OK, we have the expected gate type and personID. 
 
      // If this is an entry, keep track of it, otherwise clear tracks 
 
      collect.openEntry = collect.openEntry ? null : curr; // toggle 
 
     } else { 
 
      console.log('mismatch'); 
 
      // not OK, add to orphans list 
 
      if (collect.openEntry)  collect.orphans.push(collect.openEntry); 
 
      if (curr.gateType == 'exit') collect.orphans.push(curr); 
 
      // If this is an entry, replace previous track 
 
      collect.openEntry = curr.gateType == 'entry' ? curr : null; 
 
     } 
 
     return collect; 
 
    }, {orphans: [], openEntry: null}); // initial value of collect 
 
    
 
    // if last one was an "entry", add it to the orphans list 
 
    if (collect.openEntry) { 
 
     collect.orphans.push(collect.openEntry); 
 
    } 
 
    
 
    // for all orphans: return the missing counter part. 
 
    return collect.orphans.map(function(orphan) { 
 
     var mydate = new Date(orphan.dateTime.replace(/^(.{10}) (.{8})$/, '$1T$2Z')) 
 
     // add/subtract one second: 
 
     mydate = new Date(+mydate + 1000*(orphan.gateType == "entry" ? 1 : -1)); 
 
     return { 
 
      id:   orphan.id, 
 
      dateTime: mydate.toISOString().replace(/^(.{10})T(.{8}).*$/, '$1 $2'), 
 
      gateNumber: orphan.gateNumber, 
 
      gateType: orphan.gateType == "entry" ? "exit" : "entry", 
 
      personId: orphan.personId, 
 
      fix:  orphan.fix 
 
     }; 
 
    }); 
 
} 
 

 
// default input data: 
 
var data = [ 
 
    { 
 
    "id": 517, 
 
    "dateTime": "2016-01-29 13:17:46", 
 
    "gateNumber": "192.168.1.206", 
 
    "gateType": "exit", 
 
    "personId": 1, 
 
    "fix": 0 
 
    }, 
 
    { 
 
    "id": 568, 
 
    "dateTime": "2016-01-29 14:03:44", 
 
    "gateNumber": "192.168.1.203", 
 
    "gateType": "entry", 
 
    "personId": 1, 
 
    "fix": 0 
 
    }, 
 
    { 
 
    "id": 675, 
 
    "dateTime": "2016-01-29 14:10:07", 
 
    "gateNumber": "192.168.1.203", 
 
    "gateType": "entry", 
 
    "personId": 1, 
 
    "fix": 0 
 
    }, 
 
    { 
 
    "id": 108, 
 
    "dateTime": "2016-01-29 14:11:51", 
 
    "gateNumber": "192.168.1.205", 
 
    "gateType": "entry", 
 
    "personId": 1, 
 
    "fix": 0 
 
    }, 
 
    { 
 
    "id": 170, 
 
    "dateTime": "2016-01-28 14:27:58", 
 
    "gateNumber": "192.168.1.206", 
 
    "gateType": "exit", 
 
    "personId": 2, 
 
    "fix": 0 
 
    }, 
 
    { 
 
    "id": 66, 
 
    "dateTime": "2016-01-28 14:33:07", 
 
    "gateNumber": "192.168.1.200", 
 
    "gateType": "exit", 
 
    "personId": 2, 
 
    "fix": 0 
 
    }, 
 
    { 
 
    "id": 395, 
 
    "dateTime": "2016-01-28 16:26:04", 
 
    "gateNumber": "192.168.1.206", 
 
    "gateType": "exit", 
 
    "personId": 2, 
 
    "fix": 0 
 
    } 
 
]; 
 
// Get input controls: 
 
var input = document.getElementById('input'); 
 
var output = document.getElementById('output'); 
 
var button = document.getElementById('button'); 
 

 
// default input value: 
 
input.value = JSON.stringify(data, null, 2); 
 

 
// execute process on button click: 
 
button.onclick = function() { 
 
    var data = JSON.parse(input.value); 
 
    var missing = detectMissingOnes(data); 
 
    output.textContent = JSON.stringify(missing, null, 2); 
 
}
div { bottom: 0; right: 0; left: 0; top: 0; position: absolute } 
 
table { with: 100%; height: 100% } 
 
tr.page { with: 100%; height: 100% } 
 
td { vertical-align: top; width: 50%} 
 
textarea { min-width: 320px; width: 100%; height:100% }
<div class="big"><table border=1> 
 
    <tr><th>Enter input (JSON):<button id="button">Process</button></th> 
 
     <th>Output</th></tr> 
 
    <tr class="page"><td><textarea id="input"></textarea></td> 
 
     <td><pre id="output"></pre></td></tr> 
 
</table></div>

Функция не изменяет переданный аргумент (массив). Возвращенный массив перечисляет только отсутствующие объекты. Обратите внимание, что вам нужно адаптировать код, если у вас есть другие свойства в ваших объектах.

+0

Большое спасибо, работает как шарм! – serkan

+0

Мне нужно внести небольшие изменения, но не уверен, как это сделать. Мне нужно учитывать свойство «personId». Мне нужно проверить, имеют ли объекты одинаковые идентификаторы personId. Не могли бы вы мне помочь? большое спасибо. – serkan

+0

Не могли бы вы проверить эти данные http://pastebin.com/ECry1T0f? Кажется, он всегда пропускает два объекта. Если функция выполняется во второй раз, она также исправляет эти два элемента. – serkan

1

попробовать это:

'use strict'; 

let arr = [{ 
    "dateTime": "2016-01-28 15:18:26", 
    "gateType": "entry", 
}, { 
    "dateTime": "2016-01-28 15:18:27", 
    "gateType": "exit", 
}, { 
    "dateTime": "2016-01-28 15:19:26", 
    "gateType": "entry", 
}, { 
    "id": 7244, 
    "dateTime": "2016-01-28 15:19:27", 
    "gateType": "exit", 
}, { 
    "dateTime": "2016-01-28 15:20:26", 
    "gateType": "entry", 
}, 
// here is the exit object is missing for above 
{ 
    "dateTime": "2016-01-28 15:21:25", 
    "gateType": "entry", 
}, { 
    "dateTime": "2016-01-28 15:21:26", 
    "gateType": "exit", 
}, { 
    "dateTime": "2016-01-28 15:22:25", 
    "gateType": "entry", 
}, { 
    "dateTime": "2016-01-28 15:22:26", 
    "gateType": "exit", 
}, 
// here is the entry object is missing for below 
{ 
    "dateTime": "2016-01-28 15:23:26", 
    "gateType": "exit", 
}]; 

function repairArr(arr) 
{ 
    for(let index=0; index<arr.length; index++) 
    { 
    let item = arr[index]; 

    if(index!=0 && item.gateType == arr[index-1].gateType) 
    { 
     arr.splice(index, 0, { 
     dateTime: item.dateTime, 
     gateType: item.gateType == 'entry' ? 'exit' : 'entry' 
     }); 
    } 
    }; 
} 

repairArr(arr); 

console.log(arr); 
+0

не работает должным образом, если данные похожи на ['entry', 'entry', 'entry', 'exit', 'exit'] -> необходимо вернуть ['entry', 'exit', 'exit' 'entry', 'exit', 'entry', 'exit', 'entry', 'exit', 'entry', 'exit'], но возвращает что-то еще. – serkan

+0

https://jsfiddle.net/1r8f6cw6/1/ –

+0

@ serdem420, почему вы говорите, что он должен тогда возвращать '['entry', 'exit', 'entry', 'exit', 'entry', 'exit', ' 'entry', 'exit', 'entry', 'exit'] '. В вашем вопросе вы говорите, что он должен возвращать только отсутствующие записи, а не завершенный массив. Поэтому я ожидаю, что вывод будет следующим: '['exit', 'exit', 'exit', 'entry', 'entry']'. Просьба уточнить? – trincot