计算数组中多个 objects 的属性

Count properties of multiple objects in array

我想对多 object 数组中的元素进行计数。我该怎么做?

//constructor function
function Bookdes(title, author, pages, current_page, available){
    this.title = title;
    this.author = author;
    this.pages = pages;
    this.current_page = current_page;
    this.available = available;
}
//array of books
var bookarrays = [
    new Bookdes("Fast Cars", "John Burns", 205, 43, "true"),
    new Bookdes("Slow Cars", "Joe Fast", 70, 32, "false" ),
    new Bookdes("Big Cars", "Darla Jean", 234, 42, "true"),
    new Bookdes("Small Cars", "Dema Jones", 214, 34, "false"),
    new Bookdes("Cars", "Alex Best", 235, 41, "true")
];

现在我如何计算可用图书数 (true)、阅读页数总和 (current_page)、最长标题的长度?

谢谢,

检查此 fiddle 以进行现场演示

//constructor function
function Bookdes(title, author, pages, current_page, available){
    this.title = title;
    this.author = author;
    this.pages = pages;
    this.current_page = current_page;
    this.available = available;
}
//array of books
var bookarrays = [
    new Bookdes("Fast Cars", "John Burns", 205, 43, "true"),
    new Bookdes("Slow Cars", "Joe Fast", 70, 32, "false" ),
    new Bookdes("Big Cars", "Darla Jean", 234, 42, "true"),
    new Bookdes("Small Cars", "Dema Jones", 214, 34, "false"),
    new Bookdes("Cars", "Alex Best", 235, 41, "true")
];

function sum(){
   var i;
    var count = 0;
    var maxlen = 0;
    var read = 0;
    for(i=0; i<bookarrays.length; i++){
        if(bookarrays[i].title.length > maxlen){
             maxlen = bookarrays[i].title.length;
        }
        if(bookarrays[i].available === "true" || bookarrays[i].available === true){
             count++;   
        }
        read += bookarrays[i].current_page;

    }
    $("#out").html("Count: " + count + "<br>Maxlength: " + maxlen + "<br>read: " + read);
}

$(function(){
       sum();
});

还有一点 HTML:

<div id="out"></div>

它打印:

Count: 3
Maxlength: 10
read: 192

只需遍历每个元素并做你想做的事

Live Demo

//constructor function
function Bookdes(title, author, pages, current_page, available){
    this.title = title;
    this.author = author;
    this.pages = pages;
    this.current_page = current_page;
    this.available = available === 'true';
}
//array of books
var bookarrays = [
    new Bookdes("Fast Cars", "John Burns", 205, 43, "true"),
    new Bookdes("Slow Cars", "Joe Fast", 70, 32, "false" ),
    new Bookdes("Big Cars", "Darla Jean", 234, 42, "true"),
    new Bookdes("Small Cars", "Dema Jones", 214, 34, "false"),
    new Bookdes("Cars", "Alex Best", 235, 41, "true")
];

var available = 0;
var page = 0;
var longest = '';

for (var i = 0, max = bookarrays.length; i < max; i += 1) {
    bookarrays[i].available && (available += 1);
    page += bookarrays[i].current_page;
    longest = bookarrays[i].title.length > longest.length ? bookarrays[i].title : longest;
}

alert(available);
alert(page);
alert(longest);

函数式编程技术,一开始可能看起来有点气势磅礴,但通常会使此类问题变得更简单。使用 Ramda(披露:我是作者之一;但这些技术在许多其他函数式编程库中可用)你可以这样做:

var countAvailable = R.pipe(R.filter(R.propEq('available', 'true')), R.prop('length'));
var pagesRead = R.pipe(R.pluck('current_page'), R.sum);
var maxTitleLength = R.pipe(R.pluck('title'), R.pluck('length'), R.max);

其中每个 returns 一个函数,您可以使用 bookarrays 调用它们。您可以在 Ramda REPL.

上看到它的实际效果

要点是,像 pluck 这样的通用函数让您有机会将一个列表更改为另一个列表。所以

pluck('title')(bookarrays);
//=> ["Fast Cars", "Slow Cars", "Big Cars", "Small Cars", "Cars"]

然后你有一个更简单的列表来进一步操作。如果你调用 pluck('length'),你会得到 [9. 9, 8, 10, 4],然后你可以调用 max。因此,只需将 pluckmax 以及 pipe 组合在一起,您就可以非常轻松地创建一个函数 maxTitleLength。函数式编程经常这样做:创建可用于相同数据结构(在本例中为列表)的简单可组合函数


更新

这一切的重点不在于图书馆本身。这个想法是,如果你制作一些小的、可重复使用的、可组合的部分,你可以用它们构建更复杂的功能。下面是这样一个函数集合的开始,足以解决那些问题:

var add = function(a, b) {
  return a + b;
};

var sum = function(list) {
  return list.reduce(add, 0);
};

var max = function(list) {
  return Math.max.apply(Math, list);
};

var map = function(fn) {
  return function(list) {
    return list.map(fn);
  };
};

var prop = function(name) {
  return function(obj) {
    return obj[name];
  };
};

var pipe = function() {
    var funcs = arguments;
    return function() {
        var args = arguments;
        for (var i = 0; i < funcs.length; i++) {
            args = [funcs[i].apply(this, args)];
        }
        return args[0];
    };
};

var pluck = pipe(prop, map);

var filter = function(fn) {
  return function(list) {
    return list.filter(fn);
  };
};

var propEq = function(name, val) {
  return function(obj) {
    return obj[name] === val;
  };
}

要使用这个小库,您可以通过组合它们来编写代码。请注意 pluck 的定义是多么简单。

你也可以这样写:

var pluck = function(name) {
  return map(prop(name));
};

但是由于 pipe 以这种方式处理组合函数,我们可以简单地写

var pluck = pipe(prop, map);

显然,使用这些函数,您可以像这样为您的答案编写函数:

var countAvailable = pipe(filter(propEq('available', 'true')), prop('length'));
var pagesRead = pipe(pluck('current_page'), sum);
var maxTitleLength = pipe(pluck('title'), pluck('length'), max);

countAvailable(bookarrays); //=> 3
pagesRead(bookarrays);      //=> 192
maxTitleLength(bookarrays); //=> 10

当然,这不是完成此类任务的最简单方法。但是现在您可以使用所有这些功能,进一步的任务会更容易。这就是函数式编程的意义所在。


这会跳过函数式编程中的一个重要工具,称为 curryinga great article by Hugh Jackson on the topic, and I wrote another one 包含更多详细信息。我不会在这里详细介绍,但它会使那些功能更简单。例如,而不是

var propEq = function(name, val) {
  return function(obj) {
    return obj[name] === val;
  };
}

我们可以写

var propEq = curry(function(name, val, obj) {
  return obj[name] === val;
});

你可以像上面那样调用它,只传递 nameval 来取回接受 obj 的函数。或者您可以立即将所有三个参数传递给它:

propEq('length', 3, 'abc'); //=> true

使用 curry 函数可以进一步简化上述代码,同时使其更加灵活。