将JSON操作为可观察的数组集合

时间:2014-02-22 03:31:01

标签: javascript jquery arrays json knockout.js

我正在寻求如何处理这个JSON的建议:

[{
  "title":"Things",
  "text":"1. Raindrops on roses 2. Whiskers on kittens 3. Bright copper kettles 4. Warm woolen mittens 5. Brown paper packages"
},{
  "title":"Colors",
  "text":"1. White 2. Blue 3. Red 4. Yellow 5. Green"
},{
  "title":"Animals",
  "text":"1. Dog 2. Rabbit 3. Cat 4. Squirrel 5. Duck"
},{
  "title":"Colors",
  "text":"1. Red 2. Blue 3. Orange 4. Green 5. Purple"
},{
  "title":"Animals",
  "text":"1. Bear 2. Bird 3. Duck 4. Squirrel 5. Rabbit"
},{
  "title":"Colors",
  "text":"1. Yellow 2. White 3. Black 4. Brown 5. Blue"
}]

返回这些可观察数组的集合:

  • 标题:颜色,数量:3,项目:
    • 姓名:白人,分数:9,数:2
    • 姓名:蓝色,分数:9,数:3
    • 姓名:红色,分数:8,数:2
    • 姓名:黄色,分数:7,数:2
    • 姓名:黑人,分数:3,数:1
    • 姓名:橙色,得分:3,数:1
    • 姓名:绿色,得分:3,数:2
    • 姓名:布朗,得分:2,数:1
    • 姓名:紫色,分数:1,数:1

  • 标题:动物,数量:2,物品:
    • 姓名:熊,分数:5,数:1
    • 姓名:狗,分数:5,数:1
    • 姓名:兔子,分数:5,数:2
    • 姓名:Bird,得分:4,数:1
    • 姓名:Duck,得分:4,数:2
    • 姓名:松鼠,分数:4,数:2
    • 姓名:猫,分数:3,数:1

  • 标题:事物,数量:1,项目:
    • 姓名:玫瑰雨滴,分数:5,数:1
    • 名称:小猫上的胡须,分数:4,数:1
    • 名称:鲜铜水壶,分数:3,数:1
    • 姓名:暖羊毛手套,分数:2,数:1
    • 姓名:牛皮纸包装,分数:1,数:1

为了解释,我需要做以下事情:

  1. title对所有数组进行分组,计算其频率并返回新的List对象,例如Title: Colors, Count: 3
  2. 按编号分隔符拆分每个text项目以创建项目数组,计算其频率,根据索引位置为其分配一个分数(即[0] = 5到[4] = 1),求和得分并返回新的Item对象,例如Name: White, Score: 9, Count: 2
  3. ListsCount集合按ItemsScoreCountName集合进行排序。
  4. 我创建了以下javascript对象:

    function List(title, items, count) {
        var self = this;
            self.Title = title;
            self.Count = count;
            self.Items = ko.observableArray(items);
    }
    
    function Item(name, count, score) {
        var self = this;
            self.Name = name;
            self.Count = count;
            self.Score = score;
    }
    

    我已经研究了我打算使用underscore.js攻击此任务的各种方法,但是由于报告在迭代数组中表现不佳而被推迟。

    我预计JSON文件会比我展示的样本大得多,因此性能非常重要。

    希望有些人可以提出实现目标的最佳方法,也许可以展示一个良好的起点。

    提前致谢。

1 个答案:

答案 0 :(得分:1)

我在此示例中使用Lo-Dash 2.2.1,但您可以轻松交换Underscore.js,因为它们的库_.each签名基本相同。

Live Demo

var collection = [{
  "title":"Things",
  "text":"1. Raindrops on roses 2. Whiskers on kittens 3. Bright copper kettles 4. Warm woolen mittens 5. Brown paper packages"
},{
  "title":"Colors",
  "text":"1. White 2. Blue 3. Red 4. Yellow 5. Green"
},{
  "title":"Animals",
  "text":"1. Dog 2. Rabbit 3. Cat 4. Squirrel 5. Duck"
},{
  "title":"Colors",
  "text":"1. Red 2. Blue 3. Orange 4. Green 5. Purple"
},{
  "title":"Animals",
  "text":"1. Bear 2. Bird 3. Duck 4. Squirrel 5. Rabbit"
},{
  "title":"Colors",
  "text":"1. Yellow 2. White 3. Black 4. Brown 5. Blue"
}];

//Store all the collections in a single place.
var collections = {}; 
_.each(collection, function(item){

    //Does the collection exist?
    if(!collections[item.title]){
        //No? Add a new one
        collections[item.title] = {Title:'', Items: {} };    
    }

    //Split out the parts of the text by number period
    var parts = item.text.split(/[0-9]+\./); 
    if(parts.length > 0){
        parts.shift(); //remove the first entry in the array since it will be blank   
    }

    //Iterate over each part text we found
    _.each(parts, function(partName, i){

        partName = partName.trim(); //remove whitespace

        //Try to get an existing reference to the part
        var part = collections[item.title].Items[partName]; 

        //If the part doesn't exist
        if(!part){

            //Create a new one and add it to the collection
            part = { Score: 0, Count: 0 }; 
            collections[item.title].Items[partName] = part; 
        }

        //Increment the score by the ordinal position
        part.Score += i; 

        //Increment the count by 1
        part.Count++; 
    }); 
});


//Store the final array of collections here
var finalData = []; 

//Iterate over our current collection object
_.each(collections, function(collection, i){

    var data = []; 

    //Convert the Items "hashtables"/objects into arrays
    for(var key in collection.Items){

        data.push({
            'Name': key,    
            'Score': collection.Items[key].Score, 
            'Count': collection.Items[key].Count
        }); 

    }

    collection.Items = data; //replace the Items object with the array
    collection.Count = data.length; //compute the current count. (Although you could always call Items.length)
    finalData.push(collection); //add the collection to the array.
});

console.log(finalData); 

<强>结果

[
  {
    "Title": "Things",
    "Items": [
      {
        "Name": "Raindrops on roses",
        "Score": 0,
        "Count": 1
      },
      {
        "Name": "Whiskers on kittens",
        "Score": 1,
        "Count": 1
      },
      {
        "Name": "Bright copper kettles",
        "Score": 2,
        "Count": 1
      },
      {
        "Name": "Warm woolen mittens",
        "Score": 3,
        "Count": 1
      },
      {
        "Name": "Brown paper packages",
        "Score": 4,
        "Count": 1
      }
    ],
    "Count": 5
  },
  {
    "Title": "Colors",
    "Items": [
      {
        "Name": "White",
        "Score": 1,
        "Count": 2
      },
      {
        "Name": "Blue",
        "Score": 6,
        "Count": 3
      },
      {
        "Name": "Red",
        "Score": 2,
        "Count": 2
      },
      {
        "Name": "Yellow",
        "Score": 3,
        "Count": 2
      },
      {
        "Name": "Green",
        "Score": 7,
        "Count": 2
      },
      {
        "Name": "Orange",
        "Score": 2,
        "Count": 1
      },
      {
        "Name": "Purple",
        "Score": 4,
        "Count": 1
      },
      {
        "Name": "Black",
        "Score": 2,
        "Count": 1
      },
      {
        "Name": "Brown",
        "Score": 3,
        "Count": 1
      }
    ],
    "Count": 9
  },
  {
    "Title": "Animals",
    "Items": [
      {
        "Name": "Dog",
        "Score": 0,
        "Count": 1
      },
      {
        "Name": "Rabbit",
        "Score": 5,
        "Count": 2
      },
      {
        "Name": "Cat",
        "Score": 2,
        "Count": 1
      },
      {
        "Name": "Squirrel",
        "Score": 6,
        "Count": 2
      },
      {
        "Name": "Duck",
        "Score": 6,
        "Count": 2
      },
      {
        "Name": "Bear",
        "Score": 0,
        "Count": 1
      },
      {
        "Name": "Bird",
        "Score": 1,
        "Count": 1
      }
    ],
    "Count": 7
  }
]