Вложенный .unionWith, с одним уникальным слиянием на уровень - PullRequest
0 голосов
/ 10 января 2019

Исходные данные выглядят так:

let AddressesBook = [
{
    "userName": "Jay12",
    "doorNumber": "1512",
    "cityID": 19,
    "city": "London",
    "countryID": 1,
    "country": "UK",
    "houseType": "private"
},
{
    "userName": "Jay12",
    "doorNumber": "2003",
    "cityID": 14,
    "city": "York",
    "countryID": 1,
    "universe": "UK",
    "houseType": "private"
},
{
    "userName": "Jay12",
    "doorNumber": "435",
    "cityID": 31,
    "city": "Washington",
    "countryID": 2,
    "universe": "USA",
    "houseType": "private"
},
{
    "userName": "Jay12",
    "doorNumber": "1123",
    "cityID": 18,
    "city": "Oxford",
    "countryID": 1,
    "universe": "UK",
    "houseType": "private"
}


];

я отображал иерархию данных по соответствующему уникальному идентификатору, используя Lodash и насыщенный словарь:

function nestMaker(list, order) {
if (_.isEmpty(order)) return [];
let groups = _.groupBy(list, _.first(order));
return _.map(groups, (children, key) => {
    let group = {};
    group[_.first(order)] = key;
    group.data = nestMaker(children, _.drop(order));
    return _.isEmpty(group.data) ? _.omit(group, 'data') : group;
  });
  }


let hierarchical = nestMaker(AddressesBook, [
"countryID",
"cityID",
"houseType",
"doorNumber"]
 );

это работает нормально, но я хотел бы иметь имя, соответствующее идентификатору на каждом уровне объекта. к сожалению, вы не можете использовать _.groupBy для двух ключей. я думал об использовании _.unionWith отдельно от первой итерации, но я не мог найти способ использовать его рекурсивно, опуская ненужные данные.

ожидаемый результат:

 let output =
  [
    {
        "countryID": "1",
        "country": "UK",
        "data": [
            {
                "cityID": "14",
                "city": "York",
                "data": [
                    {
                        "houseType": "private",
                        "data": [
                            {
                                "doorNumber": "2003"
                            }
                        ]
                    }
                ]
            },
            {
                "cityID": "18",
                "city": "Oxford",
                "data": [
                    {
                        "houseType": "private",
                        "data": [
                            {
                                "doorNumber": "1123"
                            }
                        ]
                    }
                ]
            },
            {
                "cityID": "19",
                "city": "London",
                "data": [
                    {
                        "houseType": "private",
                        "data": [
                            {
                                "doorNumber": "1512"
                            }
                        ]
                    }
                ]
            }
        ]
    },
    {
        "countryID": "2",
        "country": "USA",
        "data": [
            {
                "cityID": "31",
                "city": "Washington",
                "data": [
                    {
                        "houseType": "private",
                        "data": [
                            {
                                "doorNumber": "435"
                            }
                        ]
                    }
                ]
            }
        ]
      }
    ];

Ответы [ 2 ]

0 голосов
/ 10 января 2019

Вы можете получить 1-й предмет в группе и извлечь название (страну, город) из предмета:

const AddressesBook = [{"userName":"Jay12","doorNumber":"1512","cityID":19,"city":"London","countryID":1,"country":"UK","houseType":"private"},{"userName":"Jay12","doorNumber":"2003","cityID":14,"city":"York","countryID":1,"country":"UK","houseType":"private"},{"userName":"Jay12","doorNumber":"435","cityID":31,"city":"Washington","countryID":2,"country":"USA","houseType":"private"},{"userName":"Jay12","doorNumber":"1123","cityID":18,"city":"Oxford","countryID":1,"country":"UK","houseType":"private"}];

const nestMaker = (list, order) => {
  if (_.isEmpty(order)) return [];
  
  const idKey = _.first(order);
  const nameKey = idKey.replace('ID', '');
  let groups = _.groupBy(list, idKey);
  
  return _.map(groups, (children, key) => {
    const group = {};
    const child = _.first(children);
    
    group[idKey] = key;
    if(_.has(child, nameKey)) group[nameKey] = child[nameKey];
    
    group.data = nestMaker(children, _.drop(order));
    return _.isEmpty(group.data) ? _.omit(group, 'data') : group;
  });
}


const hierarchical = nestMaker(AddressesBook, [
  "countryID",
  "cityID",
  "houseType",
  "doorNumber"
]);

console.log(hierarchical);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>

Если ключи id и name не соответствуют одному и тому же шаблону, вы можете явно указать их как запись в следующем порядке:

const AddressesBook = [{"userName":"Jay12","doorNumber":"1512","cityID":19,"city":"London","countryID":1,"universe":"UK","houseType":"private"},{"userName":"Jay12","doorNumber":"2003","cityID":14,"city":"York","countryID":1,"universe":"UK","houseType":"private"},{"userName":"Jay12","doorNumber":"435","cityID":31,"city":"Washington","countryID":2,"universe":"USA","houseType":"private"},{"userName":"Jay12","doorNumber":"1123","cityID":18,"city":"Oxford","countryID":1,"universe":"UK","houseType":"private"}];

const nestMaker = (list, order) => {
  if (_.isEmpty(order)) return [];
  
  const entry = _.first(order);
  const [idKey, nameKey] = Array.isArray(entry) ? entry : [entry];
  let groups = _.groupBy(list, idKey);
  
  return _.map(groups, (children, key) => {
    const group = {}; 
    const child = _.first(children);
    
    group[idKey] = key;
    if(_.has(child, nameKey)) group[nameKey] = child[nameKey];
    
    group.data = nestMaker(children, _.drop(order));
    return _.isEmpty(group.data) ? _.omit(group, 'data') : group;
  });
}


const hierarchical = nestMaker(AddressesBook, [
  ["countryID", "universe"],
  ["cityID", "city"],
  "houseType",
  "doorNumber"
]);

console.log(hierarchical);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
0 голосов
/ 10 января 2019

Это немного руководство, но делает работу.

let AddressesBook = [{
    "userName": "Jay12",
    "doorNumber": "1512",
    "cityID": 19,
    "city": "London",
    "countryID": 1,
    "country": "UK",
    "houseType": "private"
  },
  {
    "userName": "Jay12",
    "doorNumber": "2003",
    "cityID": 14,
    "city": "York",
    "countryID": 1,
    "country": "UK",
    "houseType": "private"
  },
  {
    "userName": "Jay12",
    "doorNumber": "435",
    "cityID": 31,
    "city": "Washington",
    "countryID": 2,
    "country": "USA",
    "houseType": "private"
  },
  {
    "userName": "Jay12",
    "doorNumber": "1123",
    "cityID": 18,
    "city": "Oxford",
    "countryID": 1,
    "country": "UK",
    "houseType": "private"
  }


];
database = []
AddressesBook.forEach(a => {
  doesExist = database.some(d => (d.countryID == a.countryID))
  if (doesExist) {
    let instance = database.filter(d => d.countryID == a.countryID)[0]
    instance.data.push({
      "cityID": a.cityID,
      "city": a.city,
      "data": [{
        "houseType": a.houseType,
        "data": [{
          "doorNumber": a.doorNumber
        }]
      }]
    })
  } else {
    database.push({
      "countryID": a.countryID,
      "country": a.country,
      "data": [{
        "cityID": a.cityID,
        "city": a.city,
        "data": [{
          "houseType": a.houseType,
          "data": [{
            "doorNumber": a.doorNumber
          }]
        }]
      }]
    })
  }
})

console.log(database)
...