ReactJS - JavaScript: функция фильтра не работает должным образом - PullRequest
1 голос
/ 27 февраля 2020

Я строю визуализатор лодки, используя AISHub APIs . После запроса API я могу получить файл json с тысячами судов, но я фильтрую только те суда, которые мне интересны, и вставляю их в таблицу на веб-странице. API предоставляет следующие поля: [NAME, MMSI, LONGITUDE, LATITUDE, others...]. Наиболее важные параметры, которые я использую для фильтрации: NAME и MMSI (хотя может быть несколько сосудов с одинаковым NAME, не может быть двух сосудов с одинаковым номером MMSI, поскольку он уникален).

Проблема У меня есть то, что функция filter, похоже, не работает должным образом. Фактически, он не фильтруется однозначно для этих спецификаций c NAME и / или MMSI, и я получаю несколько сосудов с одинаковым NAME и разными MMSI. Кроме того, судно, которое должно появиться, не появляется, несмотря на то, что я жестко закодировал NAME и MMSI для этого конкретного c судна. Это не объяснимо, так как я жестко запрограммировал эти числа для специальной фильтрации.

Ниже кода, который я использую для поиска при фильтрации:

var express = require('express');
var router = express.Router();
var axios = require('axios');
const NodeCache = require('node-cache');
const myCache = new NodeCache();

let hitCount = 0;

/* GET home page. */
router.get('/', function(req, res, next) {
    res.render('index', { title: 'Express' });
});

const mmsiOfInterest = [
    '367029520', // ok -> MICHIGAN
    '366909730', // ok -> JP BOISSEAU
    '367128570', // ok -> DELAWARE BAY
    '366744010', // ok -> ATLANTIC SALVOR
    // Other MMSI numbers .....
];


const shipNamesOfInterest = [
    'MICHIGAN',
    'JP BOISSEAU',
    'DELAWARE BAY',
    'ATLANTIC SALVOR',
    // Other NAMES....
]

router.get('/hello', async function(req, res, next) {
    const allData = myCache.get('allData');

    if (!allData) {
        hitCount++;
        console.log(`hit ${hitCount} number of times`);
        const { data } = await axios.get(
            'http://data.aishub.net/ws.php?username=MY_KEY&format=1&output=json&compress=0&latmin=11.42&latmax=58.20&lonmin=-134.09&lonmax=-52.62'
        );

        const [ metaData, ships ] = data;
        console.log(data);

        const shipsOfInterest = ships.filter(
            (ship) => mmsiOfInterest.includes(ship.MMSI) || shipNamesOfInterest.includes(ship.NAME)
        );
        myCache.set('allData', shipsOfInterest, 70);
        res.send(data);
        return;
    }

    console.log('this is the data:', allData);
    res.send(allData);
});

module.exports = router;

Также ниже типичного ответа JSON из API:

{"MMSI":225342000,"TIME":"2020-01-26 01:45:48 GMT","LONGITUDE":1.43912,"LATITUDE":38.91523,"COG":339.9,"SOG":0,"HEADING":297,"ROT":0,"NAVSTAT":0,"IMO":9822449,"NAME":"ILLETAS JET","CALLSIGN":"EAVX","TYPE":40,"A":4,"B":25,"C":4,"D":4,"DRAUGHT":0,"DEST":"IBIZA","ETA":"00-00 00:00"}

Что я сделал до сих пор:

1) Я попробовал другую комбинацию с функцией filter, и я попытался отфильтровать по MMSI, который должен быть уникальным для каждого судна, но я все равно получаю суда с одинаковыми NAME и разными MMSI (несмотря на то, что я жестко закодировал MMSI ... я не понимаю) :

const shipsOfInterest = ships.filter(
                (ship) => mmsiOfInterest.includes(ship.MMSI)
            );

После того, как я попытался выполнить фильтрацию по NAME, но это тоже не работает:

const shipsOfInterest = ships.filter(
                (ship) => shipNamesOfInterest.includes(ship.NAME)
            );

РЕДАКТИРОВАТЬ 2

router.get('/hello', async function(req, res, next) {
    //
    const allData = myCache.get('allData');

    if (!allData) {
        hitCount++;
        console.log(`hit ${hitCount} number of times`);
        const { data } = await axios.get(
            'http://data.aishub.net/ws.php?username=KEY&format=1&output=json&compress=0&latmin=11.42&latmax=58.20&lonmin=-134.09&lonmax=-52.62'
        );

        // console.log(data);
        const { metaData, ships } = data;
        const set = new Set();
        const shipsOfInterest = ships.filter((ship) => {
            if (set.has(ship.MMSI)) return false;
            set.add(ship.MMSI);
            return true;
        });
        myCache.set('allData', shipsOfInterest, 70);
        res.send(data);
        return;
    }

    console.log('this is the data:', allData);
    res.send(allData);
});

module.exports = router;

Ниже ошибки:

error

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

Ответы [ 4 ]

1 голос
/ 27 февраля 2020

В конце оператора if вы делаете res.send(data), что в основном является данными, которые вы получили от API. Вместо этого вам нужно res.send(shipsOfInterest); Кроме того, измените формат, если mmsiOfInterest list из строк в числа, потому что вы получаете числа от API.

1 голос
/ 27 февраля 2020

Полагаю, вы допустили ошибку при использовании сокращенного назначения. Используйте {} вместо [].

Вместо:

  const [ metaData, ships ] = data;

try:

  const { metaData, ships } = data;
0 голосов
/ 27 февраля 2020

Похоже, что MMSI входит в качестве числового значения c, в то время как ваш массив сравнения содержит строки. Как насчет использования массива целых чисел для вашего сравнения?

const mmsiOfInterest = [
    367029520,
    366909730, 
    367128570, 
    366744010, 
    // Other MMSI numbers .....
];
0 голосов
/ 27 февраля 2020

Итак, насколько я понимаю, отфильтрованный список содержит записи с уникальным значением MMSI. Итак, что вам нужно сделать, это:

const uniqueMMSI = new Set();
const shipsOfInterest = ships.filter(
  (ship) => {
    if (set.has(ship.MMSI)) return false;
    set.add(ship.MMSI);
    return true;
  }
);

Надеюсь, я понял ваш вопрос:)

...