Calculating the frequency of specific substrings present in the complete object

I am seeking a method to tally substrings of object values. In other words, instead of the entire object containing a string, I want it where one key equals a string. An effective Xpath in XSLT is:

count(//v[contains(.,current-grouping-key())])

However, I am struggling to achieve this using JavaScript.

I have attempted the following:

const obj = 
  [ { v: 'Bla Blu Bli' },
    { v: 'Bla Blu Bli' },
    { v: 'Bla Blu' },
    { v: 'Bla Bli' }
  ];

const count = obj.reduce( function(sums,entry) {
    sums[entry.v] = (sums[entry.v] || 0) + 1;
    return sums;
 },{});
 
console.log(count)

Unfortunately, this approach only counts exact strings. The output I receive is:

"Bla Blu Bli": 2,
"Bla Blu": 1,
"Bla Bli": 1

instead of

 "Bla Blu Bli": 2,
 "Bla Blu": 3,
 "Bla Bli": 3

Is there a way to count the substrings rather than just the exact values?

Answer №1

In order to optimize performance, this updated version is designed to execute more efficiently.

(in response to your statement I have 100k+ values made in a comment)

The approach involves creating an array solely for unique series, along with keeping track of the number of identical series copies.
The process entails navigating through this array and incrementing the count by considering other sets containing the same values,
but specifically focusing on those with larger sizes.

Set elements were utilized due to their efficiency compared to arrays, as per the documentation stating that [set].has(value) performs better than [array].includes(value).

const obj = 
  [ { v: 'Bla Blu Bli' }
  , { v: 'Bla Bli Blu' }
  , { v: 'Bla Blu'     }
  , { v: 'Bla Bli'     }
  ];

const counts = obj
  .reduce((r,o) => // creating an array with unique sets along with copy count
    {
    let 
      arr = o.v.split(' ')
    , sam = r.find(x=>(x.s.size===arr.length) && arr.every(a=>x.s.has(a)) )
      ;
    if (sam)  ++sam.n   // increment by one more copy
    else      r.push({arr, s:new Set(arr), n:1 })
       // needing array and set for next step to avoid unnecessary conversions
    return r
    },[]) 
  .reduce((c,e,_,all) =>
    {
    c[e.arr.join(' ')] = e.n  
      + all.reduce((s,x)=>((x.s.size > e.s.size && e.arr.every(a=>x.s.has(a))) ? s + x.n : s),0)
      // attempting to find inclusion only within larger sets
    return c
    },{})  

console.log(  counts  )
.as-console-wrapper {max-height: 100% !important;top: 0;}
.as-console-row::after {display: none !important;}

Answer №2

Here is an example of how you can achieve this:

const obj = 
  [ { v: 'Bla Blu Bli' }
  , { v: 'Bla Blu Bli' }
  , { v: 'Bla Blu'     }
  , { v: 'Bla Bli'     }
  ];

const counts = obj
  .map(e=>e.v.split(' ').sort((a,b)=>a.localeCompare(b)))
  .reduce((r,a,_,all)=>
    {
    let terms = a.join(' ')
    if (!r[terms])
      r[terms] = all.reduce((c,x)=>c+(a.every(v=>x.includes(v))?1:0),0);
    return r
    },{})
    
console.log(  counts )
.as-console-wrapper {max-height: 100% !important;top: 0;}
.as-console-row::after {display: none !important;}

Answer №3

To determine if a substring is present in a string, you can utilize the indexOf method or similar.

For instance:

obj = [
    {
        "v": "Bla † Blu † Bli"
    },
    {
        "v": "Bla † Blu † Bli"
    },
    {
        "v": "Bla † Blu"
    }
]

const counts = Object.fromEntries(
  obj.map(({v}) => [v, obj.reduce((acc, el) => {
    if (el.v.indexOf(v) > -1) acc++;
    return acc;
  }, 0)])
);

console.log(counts);

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Leveraging node modules in the browser using browserify - Error: fileType is not recognized

I am currently attempting to utilize the file-type npm package directly in my browser. Despite my efforts, I have encountered an error when trying to run the example code: Uncaught ReferenceError: fileType is not defined (Example code can be found here: ...

Transforming a flexible array of numerical values into a predetermined size

Currently, I am tackling a small project that involves generating linear graphs. For instance, I may need to create 10 points, but the data could be an array containing thousands of points. [1,5,3,5,6,33,9,1,12,4,2] Given the array of integers (11 values ...

Execute JavaScript code once the XMLHttpRequest has completed execution

I'm facing an issue where the JavaScript code is executing faster than the XMLHttpRequest. I am hesitant to resolve it using: setTimeout(function() {}, 100); Below is a snippet of my code: function change_country(id) { if (window.XMLHttpReques ...

Securing data in the browser using JavaScript encryption and decrypting on the server side using Node.js

After hours of trying to encrypt a message using AES256 in the browser, send it to the server, and then decrypt it, I keep encountering this server-side error: error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt Despite using crypto- ...

Display advertisement upon clicking

I am looking to enhance my HTML page by incorporating Google Adsense adverts that load up when a visitor clicks on video links. After 10 seconds, the page should automatically redirect to the video file. Any suggestions on how to achieve this? Thanks! ...

Guide on how to use a JavaScript AJAX call to download a text file in Java

I am looking to implement a way to download a text file (e.g. 'something.txt') using an AJAX call rather than just an anchor tag in HTML. Here is the HTML code: <body> <a href="#" id="exportViewRule">Export</a> </body&g ...

Conceal the Angular alert message automatically after a specified number of seconds or when the page

I recently started working with Angular and managed to implement an alert message for password reset requests in our app: Usermodel: .service('userModel', ['$q', '$http', 'authorizedTracker', function($q, $http, au ...

Discovering a specific value by locating a string in an array nested inside an object

Here is an example object that I need help searching: data = [ { type: "fruit", basket: ["apple", "pear", "orange"] }, { type: "vegetable", basket: ["carrot", "potato"] } ]; I am trying to find the item 'potato' and retu ...

Reorganizing Elements within an Array using JavaScript

Imagine I have the characters: H, M, L I want to create sorted arrays like this: var array1 = [ "H", "M", "L", "L", "M", "H" ]; My goal is to avoid having more than one unique character in the first three and last three characters when using the shuffl ...

Extracting web search result URLs using Puppeteer

I'm currently facing an issue with the code I've written for web scraping Google. Despite passing in a specific request, it is not returning the list of links as expected. I am unsure about what might be causing this problem. Could someone kindly ...

Prevent click event listener from activating if the click results in a new tab or window being opened

Occasionally, when using my web app, I need to prevent click event listeners from activating if the click is meant to open a new window or tab. For instance, in my single page application, there are links to other content. While they function well, there i ...

Twice Triggered: Firebase Cloud Function HTTPS Call

I have thoroughly reviewed the Firebase Cloud Functions reference, guides, and sample code in an attempt to solve the issue of my function being triggered twice, but so far, I have not found a solution. I also experimented with Firebase-Queue as a workarou ...

Debugging Typescript code with line numbers

When opening the console in a browser, typically the javascript line number of a function call or error message is displayed. However, my current setup involves using TypeScript, which gets compiled to Javascript. I am wondering if there is a way to retr ...

Avoid API calls by using connect-history-api-fallback

I have implemented the connect-history-api-fallback along with the page.js router. page('/', index); page('/about', about); page(); function index() { console.log("viewing index"); } function about() { console.log("viewing ...

Get rid of empty spaces in gridstack js

My latest project involves using gridstack js In the image displayed, I have highlighted the excess white space (in blue) that needs to be removed. Take a look at this visual: https://i.sstatic.net/Qgt62.jpg Any suggestions on how to eliminate this ...

Troubleshooting: Missing MapState in Vuex4 for Vue3 within an MVC project

Within my MVC project, I have successfully integrated Vue3 with Vuex4. However, I have encountered an issue specifically related to the mapState function. Upon using the following import statements, an error is triggered: import Vue from 'vue'; ...

Steps for accessing the "this" keyword within the parent function

Struggling with referencing `this` within a parent function while building a basic tab system using AngularJS. It seems like I may not have a solid grasp on the fundamentals, so any guidance would be appreciated: JavaScript: $scope.tabs = { _this: th ...

Disabling scrolling on body while scrolling a superimposed element

I am working on creating a dynamic image gallery for browsers that support Javascript. The gallery consists of thumbnails that lead to full-size photos displayed in a table layout, complete with navigation links and captions. This table is centered using f ...

Tips for choosing and deselecting data using jQuery

Is there a way to toggle the selection of data in my code? Currently, when I click on the data it gets selected and a tick image appears. However, I want it so that when I click again on the same data, the tick will disappear. How can I achieve this func ...

Issue encountered when attempting to merge all components utilizing PHP's array_combine() function

I'm working on combining two arrays in PHP using the array combine function. Everything is coming together smoothly, except for the last element which seems to be glitching out. The data I'm importing from a text file looks like this: ASN|PO Dat ...