Mathieu
Mathieu

Reputation: 4787

Javascript - transform array of javascript objects into a sorted key/value javascript object

I have a array of javascript objects of indefinite size:

var arr = [      
 {
        "Entities": 
          [
            {
              "BeginOffset": 28,
              "EndOffset": 35,
              "Score": 0.9945663213729858,
              "Text": "Tunisie",
              "Type": "LOCATION"
            },
            {
              "BeginOffset": 60,
              "EndOffset": 71,
              "Score": 0.8412493228912354,
              "Text": "Al HuffPost",
              "Type": "PERSON"
            },
            {
              "BeginOffset": 60,
              "EndOffset": 71,
              "Score": 0.9412493228912354,
              "Text": "trump",
              "Type": "PERSON"
            } 
          ],
        "File": "article1.com"
 },
 {
        "Entities": 
          [
            {
              "BeginOffset": 28,
              "EndOffset": 35,
              "Score": 0.9945663213729858,
              "Text": "france",
              "Type": "LOCATION"
            },
            {
              "BeginOffset": 60,
              "EndOffset": 71,
              "Score": 0.7412493228912354,
              "Text": "john locke",
              "Type": "PERSON"
            },
            {
              "BeginOffset": 60,
              "EndOffset": 71,
              "Score": 0.9412493228912354,
              "Text": "sawyer",
              "Type": "PERSON"
            } 
          ],
        "File": "anotherarticle.com"
      },
      {
        //and so on ...
 }
]

How to transform it to a key/value Javascript object where each file gives an array of the Persons tied to it while this data and filtering only on type="person" and score > 0.8 and sorting inside the array the Persons by starting with the highest scores (when there are more than 1 PERSON for Entities).

For example, the example above should output:

var finalObject =    {
  "article1.com": ["trump", "Al HuffPost"],//tunisisa not here because entity is a LOCATION
  "anotherarticle.com": ["sawyer"] //john locke not here because score <0.8
}

I tried reducing, mapping and filtering in all ways but always fail.

Upvotes: 0

Views: 91

Answers (2)

Robby Cornelissen
Robby Cornelissen

Reputation: 97120

The code below will create the requested output by reducing the input array to an object, filtering out the unwanted entities, reverse sorting based on score, and mapping the remaining entities to their Text attributes:

const result = arr.reduce((a, {Entities, File}) => {
  a[File] = Entities
              .filter(({Type, Score}) => Type === 'PERSON' && Score > 0.8)
              .sort((a, b) => b.Score - a.Score)
              .map(({Text}) => Text);
  return a;
}, {});

Complete snippet:

const arr = [{
    "Entities": [{
        "BeginOffset": 28,
        "EndOffset": 35,
        "Score": 0.9945663213729858,
        "Text": "Tunisie",
        "Type": "LOCATION"
      },
      {
        "BeginOffset": 60,
        "EndOffset": 71,
        "Score": 0.8412493228912354,
        "Text": "Al HuffPost",
        "Type": "PERSON"
      },
      {
        "BeginOffset": 60,
        "EndOffset": 71,
        "Score": 0.9412493228912354,
        "Text": "trump",
        "Type": "PERSON"
      }
    ],
    "File": "article1.com"
  },
  {
    "Entities": [{
        "BeginOffset": 28,
        "EndOffset": 35,
        "Score": 0.9945663213729858,
        "Text": "france",
        "Type": "LOCATION"
      },
      {
        "BeginOffset": 60,
        "EndOffset": 71,
        "Score": 0.7412493228912354,
        "Text": "john locke",
        "Type": "PERSON"
      },
      {
        "BeginOffset": 60,
        "EndOffset": 71,
        "Score": 0.9412493228912354,
        "Text": "sawyer",
        "Type": "PERSON"
      }
    ],
    "File": "anotherarticle.com"
  }
];

const result = arr.reduce((a, {Entities, File}) => {
  a[File] = Entities
              .filter(({Type, Score}) => Type === 'PERSON' && Score > 0.8)
              .sort((a, b) => b.Score - a.Score)
              .map(({Text}) => Text);
  return a;
}, {});

console.log(result);

Upvotes: 2

Udith Gunaratna
Udith Gunaratna

Reputation: 2111

For each Object, do the following.

  • Get the file name to be used as the key
  • Filter the Entities according to your requirement (type="person" and score > 0.8)
  • Then sort the filtered entities by score
  • Then map the sorted entities to their names and generate the names array
  • Assign it as the value under the file name key

var arr = [
    {
        "Entities":
            [
                {
                    "BeginOffset": 28,
                    "EndOffset": 35,
                    "Score": 0.9945663213729858,
                    "Text": "Tunisie",
                    "Type": "LOCATION"
                },
                {
                    "BeginOffset": 60,
                    "EndOffset": 71,
                    "Score": 0.8412493228912354,
                    "Text": "Al HuffPost",
                    "Type": "PERSON"
                },
                {
                    "BeginOffset": 60,
                    "EndOffset": 71,
                    "Score": 0.9412493228912354,
                    "Text": "trump",
                    "Type": "PERSON"
                }
            ],
        "File": "article1.com"
    },
    {
        "Entities":
            [
                {
                    "BeginOffset": 28,
                    "EndOffset": 35,
                    "Score": 0.9945663213729858,
                    "Text": "france",
                    "Type": "LOCATION"
                },
                {
                    "BeginOffset": 60,
                    "EndOffset": 71,
                    "Score": 0.7412493228912354,
                    "Text": "john locke",
                    "Type": "PERSON"
                },
                {
                    "BeginOffset": 60,
                    "EndOffset": 71,
                    "Score": 0.9412493228912354,
                    "Text": "sawyer",
                    "Type": "PERSON"
                }
            ],
        "File": "anotherarticle.com"
    }
];
function createObject() {
    var result = {};
    arr.forEach(function (item) {
        var fileName = item['File'];
        result[fileName] = item["Entities"]
            .filter(function (entity) {
                return (entity['Type'] === 'PERSON' && entity['Score'] > 0.8)
            })
            .sort(function (entity1, entity2) {
                return (entity1['Score'] > entity2['Score']) ? -1 : 1;
            })
            .map(function (entity) {
                return entity['Text']
            });
    });
    console.log(result);
}

createObject();

Upvotes: 0

Related Questions