Увеличьте количество посещенных сайтов, включая TLD и поддомены, выводимые в формате JSON

#javascript #arrays #json #function

#javascript #массивы #json #функция

Вопрос:

Итак, меня попросили создать алгоритм, который при вводе базового массива подсчетов и сайтов будет выводить накопленные посещения каждого TLD и поддомена, представленных в объекте JSON, который будет выдавать такие данные, как:

    1120   com
   800    google.com
   310    reddit.com
   60     mail.yahoo.com
   10     mobile.sports.yahoo.com
   50     sports.yahoo.com
   10     stackoverflow.com
   3      org
   3      wikipedia.org
   2      en.wikipedia.org
   2      es.wikipedia.org
   1      mobile.sports
   1      sports
  

Входные данные выглядят примерно так:

 // visits = [ "800,google.com",
//       "60,mail.yahoo.com",
//       "10,mobile.sports.yahoo.com",
//       "40,sports.yahoo.com",
//       "310,reddit.com",
//       "10,stackoverflow.com",
//       "2,en.wikipedia.org",
//       "1,es.wikipedia.org",
//       "1,mobile.sports" ]
  

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

 function getDomainHits(arr){

  var splitCount = [];
  var splitDomains = [];
  var domainCountDict = {"Domains" : [],"Count" : 0};

  for (var i = 0; i < arr.length; i  ){

    splitCount = arr[i].split(",");

    splitDomains = splitCount[1].split(".");


      for (var j = 0; j < splitDomains.length; j  ){


        if (!domainCountDict.Domain.includes(splitDomains[j])){

          domainCountDict.Domain.push(splitDomains[j]);

        }
      }

  }

  console.log(domainCountDict);
}
  

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

Ответ №1:

Итак, я разобрался с алгоритмом. Определите переменную — инициализируйте ее как массив и словарь для хранения обработанных данных массива.

 var splitCount = [];
var domainCountDict = {};
  

Затем вам нужно взять массив строк (arr — параметр функции) и выполнить итерацию по нему. На каждой итерации вам нужно разделить элемент string на другой массив для дальнейшей его обработки.

 for (var i = 0; i < arr.length; i  ){

    splitCount = arr[i].split(",");
...
}
  

Итак, для примера входных данных

 // visits = [ "800,google.com",
//       "60,mail.yahoo.com",
//       "10,mobile.sports.yahoo.com",
//       "40,sports.yahoo.com",
//       "310,reddit.com",
//       "10,stackoverflow.com",
//       "2,en.wikipedia.org",
//       "1,es.wikipedia.org",
//       "1,mobile.sports" ]
  

Итерация 0 будет разделена на массив [«800»,»google.com «] и присваивается переменной splitCount. Затем вам потребуется получить доступ к splitCount, и из-за форматирования ввода вам не нужно создавать цикл for. Я создал переменную для хранения текущего количества сайтов, которое всегда будет элементом 0 из-за формата входных данных.

Я не стал заморачиваться с очисткой ввода здесь, потому что у меня не было времени создать функцию map, которая превратит числовые элементы в — well… числа. Я полагался на предположение, что входные данные всегда будут иметь номер в 0-м индексе — что ужасно. Не делайте этого.

 var curCnt = 0;
  if (splitCount[0]){

    curCnt = splitCount[0];

  }
  

Этот следующий фрагмент логики немного повредил мой мозг, потому что мне нужно было найти способ сохранить каждый компонент домена и его количество в dict и определить, содержат ли другие домены компоненты, которые уже существовали, и если да, то увеличить их. Давайте создадим еще несколько массивов!

 var domain = [];
var currentDom = [];
      if (splitCount[1] != undefined amp;amp; splitCount[1]){

        domain = splitCount[1].split(".");


        for (var j = domain.length - 1; j >= 0; j--){
         ...
        }
       }
  

Выше вы увидите, что создан массив для хранения компонентов домена с именем domain и другой, называемый currentDom, для хранения компонентов, которые обрабатываются и которые уже были обработаны, потому что мы хотим убедиться, что мы учитываем com и google.com. Давайте заглянем внутрь цикла for.

     for (var j = domain.length - 1; j >= 0; j--){


       currentDom.unshift(domain.pop());

       /*console.log("current iter: "   k   "n"
                     "currentDom: "   currentDom.join(".")   "n"
                     "current count: "   curCnt   "n");*/

      if (currentDom.join(".") in domainCountDict){
        /*console.log("currentDom2: "   currentDom.join("."));
        console.log("increment existing");*/
        domainCountDict[currentDom.join(".")]  = parseInt(curCnt);  


      }
      if (!(currentDom.join(".") in domainCountDict)){
        /*console.log("currentDom3: "   currentDom.join("."));
        console.log("increment new");*/
        domainCountDict[currentDom.join(".")] = parseInt(curCnt);


        //console.log(domainCountDict);
      }

    }
  

Выше вы увидите, что я выполняю итерацию в обратном направлении в этом цикле, чтобы сначала обработать TLD, а затем домены / поддомены. Я решил удалить последний элемент из конца текущего массива и отменить его перенос в начало нового массива, currentDom. Это эффективно позволит мне работать с частью всего полного доменного имени, чтобы определить, было ли оно включено в словарь.

У меня есть несколько операторов if, чтобы определить, включен ли currentDom в массив. Мне пришлось использовать Array.join(), чтобы точно проверить, включена ли строка компонентов текущего домена в словарь. В противном случае строка currentDom будет добавлена в качестве ключа, а curCnt будет присвоенным значением. Если это так, то значение будет увеличено. Из-за моей медленной очистки ввода в назначении curCnt мне пришлось проанализировать их как Int, потому что JS динамические типы. Я уверен, что есть способ получше, но сейчас у меня болит мозг.

Наконец, убедитесь, что вы возвращаете созданный словарь вне всех этих циклов for.

Полный алгоритм приведен ниже

 // Sample output (in any order/format):
// getTotalsByDomain(counts)
//   1320    com
//   900    google.com
//   410    yahoo.com
//    60    mail.yahoo.com
//    10    mobile.sports.yahoo.com
//    50    sports.yahoo.com
//    10    stackoverflow.com
//     3  org
//     3  wikipedia.org
//     2  en.wikipedia.org
//     1  es.wikipedia.org
//     1  mobile.sports
//   1  sports

let counts = [ "900,google.com",
    "60,mail.yahoo.com", 
    "10,mobile.sports.yahoo.com", 
    "40,sports.yahoo.com", 
    "300,yahoo.com", 
    "10,stackoverflow.com", 
    "2,en.wikipedia.org", 
    "1,es.wikipedia.org", 
    "1,mobile.sports" ];

console.log(getDomainHits(counts));

function getDomainHits(arr){

  var splitCount = [];
  var domainCountDict = {};

  for (var i = 0; i < arr.length; i  ){

    splitCount = arr[i].split(",");



    var curCnt = 0;
          if (splitCount[0]){

            curCnt = splitCount[0];

          }

    var domain = [];
    var currentDom = [];
          if (splitCount[1] != undefined amp;amp; splitCount[1]){

            domain = splitCount[1].split(".");


            for (var j = domain.length - 1; j >= 0; j--){


               currentDom.unshift(domain.pop());

               /*console.log("current iter: "   k   "n"
                             "currentDom: "   currentDom.join(".")   "n"
                             "current count: "   curCnt   "n");*/

              if (currentDom.join(".") in domainCountDict){
                /*console.log("currentDom2: "   currentDom.join("."));
                console.log("increment existing");*/
                domainCountDict[currentDom.join(".")]  = parseInt(curCnt);  


              }
              if (!(currentDom.join(".") in domainCountDict)){
                /*console.log("currentDom3: "   currentDom.join("."));
                console.log("increment new");*/
                domainCountDict[currentDom.join(".")] = parseInt(curCnt);


                //console.log(domainCountDict);
              }

            }

          }

  }

  return domainCountDict;

}