【问题标题】:How do I slice an array from an array of object literals?如何从对象字面量数组中切片数组?
【发布时间】:2012-06-05 08:57:47
【问题描述】:

我有这个数组,其中每个索引都包含一个对象文字。所有对象字面量都具有相同的属性。一些对象文字对于给定属性具有相同的值,我想创建一个包含 only 那些对象文字的新数组。

我的想法是对数组进行排序,并将其切成一个新数组......

这是数组:

var arr = [];

arr[0] =
{
    country: "United States",
    num: 27
};

arr[1] =
{
    country: "Australia",
    num: 5
};

arr[2] =
{
    country: "United States",
    num: 7
};


所以,我想创建一个新数组,其中只包含属性country 为“美国”的对象。到目前为止,这是我的疯狂想法,但它不起作用:

function getNewArray(arr)
{
    var arr2 = [];

    for(var key in arr)
    {
        for(var i = 0; i < arr.length - 1; i++)
        {
            if(arr.hasOwnProperty(key) && arr[i].name == arr[i + 1].name)
            {
                    arr2[i] = arr.slice(key);
            }
        }
    }

    return arr2;
}

var arr3 = getNewArray(arr).sort();

【问题讨论】:

  • 您能否澄清您的问题:您的“美国”示例听起来像是您想指定一个国家/地区并仅返回该国家/地区的元素,但您的初始段落似乎在说结果应包括具有重复项的任何国家/地区。一些答案是一种方式,另一些是另一种方式(我刚刚更新了我的答案以涵盖两者)。也许您可以更新您的示例数组以包含两个以上的国家/地区?
  • 对不起,我实际上是在尝试返回一个仅包含匹配值的数组。最近事实证明,我需要这样一种算法,它可以从一个数组中返回多个数组,每个数组只包含指定的匹配值..

标签: javascript arrays sorting slice object-literal


【解决方案1】:

“我想创建一个新数组,其中仅包含属性国家为“美国”的对象”

这正是Array.filter() method 的用途:

var filteredArray = arr.filter(function(val, i, a) {
                                  return val.country==="United States";
                    });

请注意,.filter() 方法在版本 9 之前的 IE 中不可用,但我上面链接到的 MDN 页面向您展示了如何实现它,因此阅读该页面本身就应该回答您的问题。

还要注意,在问题的(非工作)代码中,您的两个 for 循环基本上是在做同样的事情,因为它们都在迭代 arr,所以它不会感觉像这样嵌套它们。你不应该在数组上使用 for..in 循环,但如果你这样做 key 值将是数字索引,它不会以某种方式获取存储在每个索引处的对象的属性。

编辑:

“某些对象文字对于给定属性具有相同的值,我想创建一个仅包含这些对象文字的新数组。”

好的,重新阅读这篇文章我猜你并不是真的想通过指定国家来选择元素,你想为任何有重复条目的国家选择元素?因此,如果还有另外三个元素都具有“新西兰”,您是否希望在 除了“美国”元素之外选择它们?如果是这样,你可以这样做:

var countryCount = {},
    i;
for (i = 0; i < arr.length; i++)
    if (countryCount.hasOwnProperty(arr[i].country)
       countryCount[arr[i].country]++;
    else
       countryCount[arr[i].country] = 1;

var filteredArr = arr.filter(function(val, i, a) {
                      return countryCount[val.country] > 1;
                  });

【讨论】:

  • 这实际上更接近我现在想要做的,它返回一个单独的数组(从原始数组),它只包含指定的匹配值......并为每个返回多个单独的数组一组匹配值,而不是像您在此处建议的那样具有所有匹配值的集合。但这非常有用,谢谢@nnnnnn。
【解决方案2】:
var getCountry = function (country) {
    var out = [];
    for (var i = 0, len = arr.length; i < len; i++)
        if (arr[i].country === country) out.push(arr[i]);
    return out;
};

演示: http://jsfiddle.net/YwytD/1/

【讨论】:

  • 这是一段不错的代码,非常简单!这正是我所需要的,这让我走上了正轨。但是,现在我很困惑,不知道究竟是哪个国家,也可能不是,以及如何从原始数组中初始化它。
  • arr 是从哪里来的?
【解决方案3】:

有一种更简单的方法,我认为这就是你想要的 var new_arr = arr.filter(function(obj){ return obj['country'] === 'United States'; }) 这会将您的结果过滤到 new_arr 当然,你可以让它变得更好、更通用,而不仅仅是“美国”

编辑: 哎呀,刚才有你的问题

答案:嵌套过滤器:)

function getKeyStuff(key) {
    return arr.filter( function(obj) { 
        var new_arr = arr.filter( function(inner_obj) { 
            return inner_obj[key] === obj[key]; 
        });
        return new_arr.length > 1; 
    });
}

【讨论】:

  • 这太棒了,我会完全使用这个想法,只是我的代码需要兼容所有版本的 IE,其中.filter() 不幸的是(IE 很烂!)。跨度>
  • 谢谢 :) 那条评论让我很开心
【解决方案4】:

这是我的解决方案:

// assuming arr is already set

var num_obj = arr.length;
var obj_by_country = {}, obj;
for (var i = 0; i < num_obj; i++) {
  obj = arr[i];
  if (!obj_by_country[obj.country]) {
    obj_by_country[obj.country] = [];
  }
  obj_by_country[obj.country].push(obj);
}

// build final array
var final_array = [];
for (i in obj_by_country) {
  if (obj_by_country[i].length > 1) {
    final_array.push(obj_by_country[i]);
  }
}

【讨论】:

    【解决方案5】:

    你会用 JQuery 吗?

    var arr = [];
    arr[0] = { country: "United States", num: 27 };
    arr[1] = { country: "Australia", num: 5 };
    arr[2] = { country: "United States", num: 7 };
    
    var newArray = [];
    $.each(arr, function(){
       if(this.country == "United States")
          newArray.push(this);
    });
    

    【讨论】:

    • 如果你要使用jQuery,为什么不使用.grep() method
    • 感谢 nnnnnn 和 @Itiong_sh 的 jQuery 选项——这两个都是我正在寻找的,并且是跨浏览器兼容的。实际上我最终可能最终会使用这样的 jQuery 算法,但是之前的答案帮助我弄清楚了我的逻辑。
    【解决方案6】:
    getByKey = function(arr, key, value) {
        var results = [];
        for(var i = 0; i < arr.length; i++) {
           if(arr[i][key] === value) {
               results.push(arr[i]);
           }
        }
        return results
    }
    

    这是一个工作示例 http://jsfiddle.net/michaelghayes/UyHYz/2/

    【讨论】:

    • 我没有投反对票,但这行不通。我想你的意思是if (arr[i][key] === value),你可能打算推送arr[i]。目前您的代码从不在循环中使用i...
    • 谢谢,有点着急,修好了
    • 这个和elclanrs的方案很像,简单有效。但是,这稍微复杂一些,因为我认为在大多数情况下我不需要两个额外的参数 keyvalue
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-08-07
    • 1970-01-01
    • 2012-11-10
    • 1970-01-01
    • 1970-01-01
    • 2021-12-28
    相关资源
    最近更新 更多