What is the best way to sort through an array depending on a specific sequence of elements provided

I am trying to create a custom pipe in Angular 5 that filters an array of events based on a given sequence. For instance, if my data is:

["submit", "click", "go_back", "click",...]

I want to filter this data based on up to three inputs. If input 1's value is "click", then I should only return events with all click occurrences. Additionally, if my input sequence is ["click", "submit", "go_back"], the output should only contain occurrences of that specific sequence.

["click","submit","go_back","click","submit","go_back","click",...]

I need to implement this functionality using array functions within an Angular pipe component. The sequence inputs are optional and limited to three. Currently, I have attempted to achieve this filtering logic with the following code:

transform(events: any[], event1?: string, event2?: string, event3?: string): any {
        if (!events) { return []; }
     
        if (event1) {
            if (event2) {
                if (event3) {
                    return events.filter((event, i) => {
                        // event.event represents the name of the event
                        return (event.event === event3 && events[i-1].event === event2 && events[i-2].event === event1);
                    });
                } else {
                    console.log("here");
                    return events.filter((event, i) => {
                        return event.event === event2 && events[i-1].event === event1;
               });
          } else {
              return events.filter((event, i) => event.event === event1);
          }
       } else {
           return events;
       }
     }

Unfortunately, the current implementation or any other method I have tried so far results in displaying only the first event. In some cases, it shows each occurrence of the initial event types but still matching the specified sequence (e.g., "click" appearing n times for n matching sequences).

Answer №1

It seems like you were almost there, but you were only capturing one element in each of your matched patterns. To improve your code, instead of:

return events.filter((event, i) => {
    return event.event === event2 && events[i-1].event === event1;
});

You should consider:

return events.filter((event, i) => {
    return event.event === event2 && events[i-1].event === event1 ||
        events[i+1].event === event2 && event.event === event1;
});

I have set up Plunker to assist you further. While I made some refinements in the code, do not hesitate to incorporate those additional matches as demonstrated above.

transform(events: Event[], ...pattern: string): Event[] {
    const matches = (event: Event, name: string) => event && event.event === name;
    const matchesPattern = (events: Event[], pattern: string[]) =>
        events.length === pattern.length && events.every((event, i) => matches(event, pattern[i]));

    switch (pattern.length) {
        case 1:
            return events.filter(event => matches(event, pattern[0]));

        case 2:
            return events.filter((event, i) =>
                matchesPattern(events.slice(i, i + 2), pattern) ||
                matchesPattern(events.slice(i - 1, i + 1), pattern));

        case 3:
            return events.filter((event, i) =>
                matchesPattern(events.slice(i, i + 3), pattern) ||
                matchesPattern(events.slice(i - 1, i + 2), pattern) ||
                matchesPattern(events.slice(i - 2, i + 1), pattern));

        default:
            return events;
    }
}

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

Attempting to implement a typeguard in Typescript that relies on the presence of specific content within an element

Currently, I am attempting to develop a Typescript conditional that verifies if a particular word is already present in the name. The function in question is as follows: isOrganic() { for (let i = 0; i < this.items.length; i++) { if(this.ite ...

Automatic execution of expressions in browserify upon initialization

Utilizing browserify alongside node.js allows me to utilize require() in my JavaScript files. Within my game.js file, I have the following code: var game = new Phaser.Game(800, 600, Phaser.AUTO, 'snakeGame'); var menuState = require('./me ...

Updating the value of a Javascript variable from a separate file

Hello there! I have a file named map.php and I need to modify the center value in the code to be based on a different value provided by another JavaScript file called template.js. In the past, I was able to change other HTML values using setAttribute and q ...

Increase the dimensions of the jQuery modal confirmation box

I am working on a jQuery confirmation dialog that displays some details for the user. My goal is to have the dialog adjust its dimensions after the user clicks "YES" to show a smaller text like "Please wait...". How can I dynamically change the size of the ...

What are the steps to expand the express object with TypeScript?

I am facing an issue where, after compiling a typescript project, the express import import {Request, Response} is not showing up. I am now attempting to use require, but I am unsure of how to extend the express object and utilize req and res. Any assistan ...

Ways to obtain the component reference when clicking in Angular 2?

<!--snippet from template file--> <custom-element ... other attributes (click)="handleClick()" </custom-element> @Component({ //selector and templateUrl }) class MainComponent{ handleClick(){ // Obtaining the re ...

ngx-bootstrap: Typeahead, receiving an unexpected error with Observable

Encountering an error whenever more than 3 characters are typed into the input box. Error message: TypeError: You provided an invalid object where a stream was expected. Acceptable inputs include Observable, Promise, Array, or Iterable. .html file : < ...

The pre-line white-space property is not functioning as anticipated in my CSS code

content: string; this.content = "There was an issue processing your request. Please try using the browser back button."; .content{ white-space: pre-line; } <div class="card-body text-center"> <span class="content"> {{ content }} </span& ...

Discovering the object and its parent within a series of nested arrays

Is there a way to locate an object and its parent object within a nested array of unknown size using either lodash or native JavaScript? The structure of the array could resemble something like this: name: 'Submodule122'</p> I have been ...

What is the reason behind the ability to access the result of a redux call "immediately" by wrapping it into a promise?

Currently, we are operating in a Redux (with thunk middleware) / React environment. The piece of code below is causing some issues: onMyClick = () => { this.props.mySynchronousActionWhichWillCreateNewReducerState(); this.setState(...my state ch ...

Uncovering the hidden gems within a data attribute

Trying my best to explain this clearly. What I have is a data-attribute that holds a large amount of data. In this case, I need to extract each individual basket product ID and display them as separate strings. The challenging part for me is locating thi ...

Changing a C# Datetime type to a Date using javascript in an ASP.NET MVC Razor web application

Having trouble converting dates in JavaScript? Check out this code snippet: $(document).ready(function () { var date = new Date(); var d = date.getDate(); var m = date.getMonth(); var y = date.getFullYear(); ...

Utilize JavaScript to reference any numerical value

I am attempting to create a button that refreshes the page, but only functions on the root / page and any page starting with /page/* (where * can be any number). Below is the code I have written: $('.refresh a').click(function() { var pathNa ...

Direction of Scrolling

Is it possible to have a div move in the opposite direction of mouse scroll, from the top right corner to the bottom left corner? Currently, it is moving from the bottom left to the top right. #block { position: absolute; top: 400px; left: 100px; < ...

What is the best way to bring in the angular/http module?

Currently, I am creating an application in Visual Studio with the help of gulp and node. Node organizes all dependencies into a folder named node_modules. During the build process, gulp transfers these dependencies to a directory called libs within wwwroo ...

Finding the main page URL using PHP within a JavaScript include: A comprehensive guide

I am facing an issue where I have a page with a header include that needs the phone number to change only if the filename of the current page contains a specific word. Typically, for a change outside of an include, the following code would suffice. <? ...

A guide on using FileReader to efficiently read multiple images

I need to be able to select multiple images from one input and read them using File Reader. If I leave it as is, it only gives me one picture. const [image , setImage] = useState(''); const [imageSelected , setImageSelected] = useState(nul ...

Navigate to items within a content block with a set height

I have a <div> that has a fixed height and overflow-y: scroll. Inside this div, there is mostly a <p> tag containing a long text with some highlighting (spans with background-color and a numbered id attribute). Just to note, this is an HTML5 a ...

Sending multiple HTTP requests sequentially

I've been attempting to send a request object to a server repeatedly in a loop, aiming to execute the task 1000 times. The scenario is reminiscent of the movie Office Space, where a small sum is extracted from numerous bank accounts. Here's the ...

Utilize an external JavaScript function within a React and TypeScript document

I have encountered an issue in my React/Next.js/TypeScript file where I am trying to load the YouTube iframe API in my useEffect hook. Here is the code snippet: useEffect(() => { const tag = document.createElement('script'); tag.src = ...