计算另一个对象数组中一个对象数组中值的出现

时间:2019-05-22 06:35:10

标签: javascript arrays object graphql

我需要创建一个Graphql查询,该查询从两个对象数组输出数据。数组是:

  const authors = [
    {
      name: 'Robert Martin',
      id: 'afa51ab0-344d-11e9-a414-719c6709cf3e',
      born: 1952
    },
    {
      name: 'Martin Fowler',
      id: 'afa5b6f0-344d-11e9-a414-719c6709cf3e',
      born: 1963
    },
    {
      name: 'Fyodor Dostoevsky',
      id: 'afa5b6f1-344d-11e9-a414-719c6709cf3e',
      born: 1821
    },
    {
      name: 'Joshua Kerievsky', // birthyear not known
      id: 'afa5b6f2-344d-11e9-a414-719c6709cf3e'
    },
    {
      name: 'Sandi Metz', // birthyear not known
      id: 'afa5b6f3-344d-11e9-a414-719c6709cf3e'
    }
  ];

并且:

  const books = [
    {
      title: 'Clean Code',
      published: 2008,
      author: 'Robert Martin',
      id: 'afa5b6f4-344d-11e9-a414-719c6709cf3e',
      genres: ['refactoring']
    },
    {
      title: 'Agile software development',
      published: 2002,
      author: 'Robert Martin',
      id: 'afa5b6f5-344d-11e9-a414-719c6709cf3e',
      genres: ['agile', 'patterns', 'design']
    },
    {
      title: 'Refactoring, edition 2',
      published: 2018,
      author: 'Martin Fowler',
      id: 'afa5de00-344d-11e9-a414-719c6709cf3e',
      genres: ['refactoring']
    },
    {
      title: 'Refactoring, edition 3',
      published: 2018,
      author: 'Martin Fowler',
      id: 'afa5de00-344d-11e9-a414-719c6709cf3e',
      genres: ['refactoring']
    },
    {
      title: 'Refactoring, edition 4',
      published: 2018,
      author: 'Martin Cowler',
      id: 'afa5de00-344d-11e9-a414-719c6709cf3e',
      genres: ['refactoring']
    },
    {
      title: 'Refactoring to patterns',
      published: 2008,
      author: 'Joshua Kerievsky',
      id: 'afa5de01-344d-11e9-a414-719c6709cf3e',
      genres: ['refactoring', 'patterns']
    },
    {
      title: 'Practical Object-Oriented Design, An Agile Primer Using 
       Ruby',
      published: 2012,
      author: 'Sandi Metz',
      id: 'afa5de02-344d-11e9-a414-719c6709cf3e',
      genres: ['refactoring', 'design']
    },
    {
      title: 'Crime and punishment',
      published: 1866,
      author: 'Fyodor Dostoevsky',
      id: 'afa5de03-344d-11e9-a414-719c6709cf3e',
      genres: ['classic', 'crime']
    },
    {
      title: 'The Demon ',
      published: 1872,
      author: 'Fyodor Dostoevsky',
      id: 'afa5de04-344d-11e9-a414-719c6709cf3e',
      genres: ['classic', 'revolution']
    }
  ];

查询的所需输出格式:

query {
  allAuthors {
  name
  bookCount
 }

}

就像这样:

    "data": {
      "allAuthors": [
        {
          "name": "Robert Martin",
          "bookCount": 2
        },
        {
          "name": "Martin Fowler",
          "bookCount": 1
        },
        {
          "name": "Fyodor Dostoevsky",
          "bookCount": 2
        },
        {
          "name": "Joshua Kerievsky",
          "bookCount": 1
        },
        {
          "name": "Sandi Metz",
          "bookCount": 1
        }
      ]
    }

我找到了一种计算每位作者的书籍数量并以所需格式输出数据的方法(此处是一个很好的示例:Summarize count of occurrences in an array of objects with Array#reduce)。但是,这种方法会忽略数据中的其他字段,例如“出生”和“类型”。如果我要像这样扩展查询:

    query {
     allAuthors {
      name
      bookCount
      born
     }
   }

对于“出生”字段不会输出任何内容。创建查询解析器的聪明方法是什么?传播运算符?减少?

*编辑* 我在这里计算书本不必要的复杂解决方案:

 const newBooks = books.reduce((acc, cv) => {
    const arr = acc.filter(obj => {
      return obj.author === cv.author;
    });

    if (arr.length === 0) {
      acc.push({ name: cv.author, born: cv.born, bookCount: 1 });
    } else {
      arr[0].bookCount += 1;
    }

    return acc;
  }, []);
  const array = [];
  books.forEach(book => {
    const object = {
      name: book.author
    };
    array.push(object);
    return array;
  });
  const unique = array.map(a => a.name);
  result = {};
  for (var i = 0; i < unique.length; ++i) {
    if (!result[unique[i]]) result[unique[i]] = 0;
    ++result[unique[i]];
  }
  const entries = Object.entries(result);
  const finalAnswer = [];
  entries.forEach(entry => {
    const object = {
      name: entry[0],
      bookCount: entry[1]
    };
    finalAnswer.push(object);
    return finalAnswer;
  });
  console.log(finalAnswer);

2 个答案:

答案 0 :(得分:3)

您可以map个作者,并使用filter来获得每个<Button variant="contained" color="" className={classes.button} onClick={this.handleOpen}> <AddIcon className={classes.leftIcon} /> Add a task </Button> 的{​​{1}}

bookCount

答案 1 :(得分:2)

我认为您可以在reducer函数中添加一条语句以添加所需的字段。我添加了单行,并注释了该方法的其余部分,以便您了解发生了什么:

const newBooks = books.reduce((acc, cv) => {
    // acc is an "accumulation" of the results so far.
    // cv is the next item that hasn't been processed.

    // Search for author in "accumulator" array acc. Put results in arr.
    const arr = acc.filter(obj => {
      return obj.author === cv.author;
    });

    if (arr.length === 0) {
      // Haven't seen this author, yet. Add new item to "accumulator" array.
      acc.push({ name: cv.author, born: cv.born, bookCount: 1 });
    } else {
      // This author already exists in "accumulator" array, referenced by arr[0].
      // Update pre-existing item.
      arr[0].bookCount += 1;
      arr[0].born = cv.born;  // <-- This is the new code that is required.
    }

    return acc;
}, []);