所访问站点的增量计数,包括输出到JSON的TLD和子域

时间:2019-03-13 00:59:52

标签: javascript arrays json function

因此,我被要求创建一种算法,当给出计数和站点数组的基本输入时,它将输出对JSON对象中表示的每个TLD和Subdomain的累积访问,从而产生如下数据:

   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 个答案:

答案 0 :(得分:0)

所以我想出了算法。定义一个变量-将其初始化为Array,以及一个字典来存储处理后的数组数据。

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

然后,您需要获取字符串数组(arr-函数参数)并对其进行迭代。在每次迭代中,您都需要将字符串元素拆分为另一个Array来进一步处理它。

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”]数组并分配给Var splitCount。然后,您将需要访问splitCount,并且由于输入格式的原因,您无需创建for循环。我创建了一个变量来存储站点的当前计数-由于输入数据的格式,该变量始终为元素0。

我在这里没有打扰输入卫生,因为我没有时间创建一个将数字元素转换为-很好...数字的映射函数。我假设输入数据将始终在第0个索引中有一个数字-这太糟糕了。不要这样做。

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

    curCnt = splitCount[0];

  }

下一个逻辑块对我的大脑造成了一点伤害,因为我需要找到一种方法来将每个域组件及其数量存储在dict中,并确定其他域是否包含已经存在的组件,以及是否增加这些组件。让我们做更多的数组!

var domain = [];
var currentDom = [];
      if (splitCount[1] != undefined && 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的开头。这将有效地使我处理整个FQDN的一部分,以确定它是否已包含在词典中。

我有一些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 && 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;

}