2012-04-26 63 views
3

我有一個無限範圍的集合(可以是0,可以是1000,可以是一百萬)。我需要搜索集合中每個模型的屬性,並返回相同的屬性(及其值)。Backbone.js:比較一個集合中的模型屬性

舉例來說,如果我有收集以下三種模式:

modelOne: 
    color: "red" 
    age: 10 
    size: "large" 

modelTwo: 
    color: "red" 
    age: 11 
    size: "medium" 

modelThree: 
    color: "red" 
    age: 9 
    size: "large" 

我需要的應用程序返回color: "red"(或可以分析一些其他的推導),因爲它是唯一的屬性,在所有三種模型中都是相同的。

編輯 John Munsch的解決方案工作得很好,但現在需求發生了變化,因爲現在有些屬性可以是數組。有沒有辦法比較數組的常規屬性屬性?

新的代碼示例:

modelOne: 
    color: "red" 
    age: 10 
    sizes: ["small", "large"] 

modelTwo: 
    color: "red" 
    age: 9 
    sizes: ["small", "large"] 
+0

如果您還有其他問題,請發帖提問 – tkone 2012-04-27 14:54:29

+0

@tkone真的嗎?即使它只是同一個問題的一個變種?這對我來說似乎很奇怪。 – 2012-04-27 16:07:38

+0

@Kevin Whitaker我不清楚在這種情況下,如果兩個數組是「尺寸:[」小「,」大「]和」尺寸:[「小」],那麼通用性會是什麼。這種情況還是「尺寸:[」小「]」,因爲他們都有一個小尺寸的紅色? – 2012-04-27 16:09:13

回答

3

這裏有一個快速的jsfiddle與我的版本的答案:http://jsfiddle.net/JohnMunsch/3NMGD/

注:兩個的jsfiddle及以下已更新的代碼,以反映該變更的要求題。

var model = [ 
    { 
     color: "red", 
     age: 10, 
     size: [ "small", "large" ] 
    }, 
    { 
     color: "red", 
     age: 11, 
     size: [ "small", "large" ] 
    }, 
    { 
     color: "red", 
     age: 9, 
     size: [ "small", "large" ] 
    } 
]; 

function findCommonalities(data) { 
    if (data.length > 0) { 
     // It's safe enough to get the list of keys from the very first 
     // element. If the later ones differ, you know that the keys they 
     // had but the first element didn't are guaranteed not to be in 
     // the common set anyway because the first element didn't 
     // have them. 
     var keys = _.keys(data[0]); 
     var commonalities = { }; 

     _.each(keys, 
      function (key) { 
       var values = _.pluck(data, key); 

       if (values.length == data.length) { 
        // Sadly calling _.uniq() won't work when the values 
        // plucked out are arrays themselves. It calls === 
        // and that's not sufficient for arrays. 
        if (_.isArray(values[0])) { 
         // However, we can get a little tricky here. 
         // What if we _.zip() together all of the arrays 
         // (assuming the ordering for each array is the 
         // same) then we'll end up with an array of 
         // arrays where each one can again be tested 
         // with _.uniq() because each one will contain 
         // the same value taken from each array. 
         var zippedValues = _.zip(values); 
         console.log("zippedValues", zippedValues); 

         if (!_.find(zippedValues, 
          function (zippedValue) { 
           var uniqueValues = _.uniq(zippedValue); 

           // Note: This test is the inverse of the 
           // one below. We're trying to find any 
           // array that has more than one value in 
           // it. If we do then there's some 
           // variance. 
           return uniqueValues.length != 1; 
          })) { 
          // We didn't find any arrays that had any 
          // variance so we want this as well. 
          commonalities[key] = values[0]; 
         } 
        } else { 
         var uniqueValues = _.uniq(values); 

         if (uniqueValues.length == 1) { 
          commonalities[key] = uniqueValues[0]; 
         } 
        } 
       } 
      } 
     ); 

     return commonalities; 
    } else { 
     return { }; 
    } 
} 

console.log("commonalities: ", findCommonalities(model)); 

性能優良似乎一個小數字鍵和少量的物品,但你需要有一百萬條記錄和大量鍵來測試它。

+0

我試了要添加一個解決方案,但我的方法有點混亂:) – fguillen 2012-04-26 16:22:16

+0

@Johnson Munsch - 這個解決方案太棒了。最後一塊 - 我的需求已經改變,現在對象的一些屬性可以是數組。我正在更新我的問題,但有沒有辦法修改您的解決方案來比較屬性是數組? – 2012-04-27 14:48:35

+0

@Kevin Whitaker更新後反映您更改的要求。可悲的是,它已經不再那麼優雅了,大約是它的兩倍:或許其他人可以提出一個比我第一次遇到的更好的解決方案 – 2012-04-27 16:25:20