0

I am using this code to fetch 100 trending public repos on GitHub.

For every language, I calculated the The list of repos using the language, but I can't calculate the number of repos using this language

part of my code

const api_url =
    "https://api.github.com/search/repositories?q=created:>30&sort=stars&order=desc&per_page=100";
  const response = await fetch(api_url);
  const data = await response.json();

  var urls = data.items
      .map((a) => ({
        language: a.language,
        url: a.url,
      }))
      .filter((el) => {
        return el.language != null;
      }),
    result = urls.reduce((r, { language, url }) => {
      match = r.find((item) => language in item);
      match ? match[language].push(url) : r.push({ [language]: [url] });

      return r;
    }, []);

This is sample of my output

[{
"Vala": [
"https://api.github.com/repos/p-e-w/finalterm"
]},
{
"Swift": [
"https://api.github.com/repos/louisdh/panelkit",
"https://api.github.com/repos/hyperoslo/Whisper",
]},
{
"C": [
"https://api.github.com/repos/wishstudio/flinux",
"https://api.github.com/repos/Sunzxyong/Tiny"
]}]

My desired output is to count the URLs of each language and append it to its corresponding language

1
  • 2
    Add the count where? { "Vala": [ "https://api.github.com/repos/p-e-w/finalterm" ], count: 1}? You could just go through each language and get the .length of the array. Commented May 12, 2021 at 15:24

4 Answers 4

1

Some changes:

  • reduce urls to an object because it's faster to lookup entries than array.find and generally less complex.
  • take the object and generate an array with language, url list for that language, and count (which is just url list length).

const urls = [
  {language: "java", url: "url1"},
  {language: "java", url: "url2"},
  {language: "php", url: "url3"},
  {language: "javascript", url:"url4"},
  {language: "php", url: "url5"},
  {language: "java", url: "url6"}
];

result = Object.entries(
  urls.reduce((r, { language, url }) => {
    if (!r[language]) r[language] = [];
    r[language].push(url);
    return r;
  }, {})
).map(([language, urls]) => (
  {language, urls, count: urls.length}
));

console.log(result);

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks alot for your answer, it really helped me.
0

Simplest approach would consist in changing your acc type from [] to {} that could carry a count property:

const urls = [{
  language: "Javascript",
  url: "url1"
}, {
  language: "Python",
  url: "url2"
}, {
  language: "Javascript",
  url: "url3"
}]

const result = urls.reduce((r, {
  language,
  url
}) => {
  if (r[language]) {
    r[language].urls.push(url)
    r[language].count ++

  } else {
    r[language] = { urls: [url], count : 1 }
  }
  
  return r;
}, {});

console.log(result)

Alternatively, to avoid looping 3 times on the items array, you could do all your operations from map et filter within the reduce

Comments

0

This is how you can do it with map:

    console.log([{
    "Vala": [
    "https://api.github.com/repos/p-e-w/finalterm"
    ]},
    {
    "Swift": [
    "https://api.github.com/repos/louisdh/panelkit",
    "https://api.github.com/repos/hyperoslo/Whisper",
    ]},
    {
    "C": [
    "https://api.github.com/repos/wishstudio/flinux",
    "https://api.github.com/repos/Sunzxyong/Tiny"
    ]}].map((item) => {return {[Object.keys(item)[0]]: item[Object.keys(item)[0]].length}}));

Comments

0

simply do

let output = Object.entries( data.items.reduce((res,{url,language})=>
  {
  res[language] = res[language] ?? []
  res[language].push(url)
  return res
  },{})
).map(([k,v])=>({[k]:v, count: v.length}))

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.