What is the process for preloading a Ramda curried function with items from an Array?

In my project, I have a collection called tagsList that contains approximately 20 tags, and another array called termIds which holds up to 3 tag ids.

My current task involves identifying tags in the tagsList that match the ids in termIds, and then applying specific styling to them. I am looking to achieve this without using traditional for loops or object-oriented programming, and instead, opting for a functional programming approach with the help of Ramda curry.

A typical tag in the tagsList looks like this:

{
    term: 'hi',
    id: 123
}

An example of termIds could be [123, 345, 678]

My objective is to iterate through the tags in the tagsList and assign a new key like border1:true, border2:true, and so on, based on the matching tag ids present in termIds.

Goal:

The main goal is to compare the tag ids in the tagsList with those in termIds and apply specific styling to the matching tags. Each matched tag should receive a unique border style, such as border1, border2, and border3 based on the matching order.


Initial Approach:

const checkId = _.curry((term_id, tag) => {
    if (tag.id === term_id) {
        console.log('match found!', tag)
    }
});

const matchId = checkId(termIds);

const coloredTags = R.map(matchId, tagsList);
console.log('coloredTags', coloredTags)
return tagsList;

However, this approach failed as I mistakenly preloaded the entire termIds array into the checkId function instead of loading individual items.

Subsequently, I attempted the following solution, which I anticipated would work but encountered an unexpected error:

const matchId = R.forEach(checkId, termIds);

https://i.sstatic.net/SWiWE.png

Answer №1

Here is a practical solution:

R.map(tag => {
  const index = R.indexOf(tag.id, termIds);
  return (index > -1) ? R.assoc('border' + (index + 1), true, tag) : tag
})(tagsList); 

//=> [
//   {id: 123, term: "hi", border1: true},
//   {id: 152, term: "ho"},
//   {id: 345, term: "hu", border2: true},
//   {id: 72,  term: "ha"}
// ]

Even though it could potentially become point-free with a lot of effort, it might sacrifice readability.

You can test this out on the Ramda REPL.

If you wish to turn this into a reusable function, follow this approach:

const addBorders = R.curry((terms, tags) => R.map(tag => {
  const index = R.indexOf(tag.id, terms);
  return (index > -1) ? R.assoc('border' + (index + 1), true, tag) : tag
})(tags))

addBorders(termIds, tagsList)

(Using curry is a common practice in Ramda. This way, you can call addBorders(termIds) and receive a reusable function that awaits the tags. If this is not needed, you can skip the curry wrapper.)

This version is also available on the Ramda REPL.

Answer №2

In my opinion, relying solely on vanilla JavaScript is more than sufficient to accomplish this task without the need for Ramda. All you need is a simple mapping function :

const tagsList = [{term: 'hello', id: 123}, {term: 'world', id: 456}, {term: 'goodbye', id: 789}];
const idList = [123, 789, 999];
let count = 1;
const updatedList = tagsList.map(item => {
  if (idList.includes(item.id)) item["index" + (count++)] = true; 
  return item;
});
console.log(updatedList);

Answer №3

Ah, I just had a breakthrough moment! I realized that I needed to curry the logic for the second time:

const matchId = R.curry((tag, term_id) => {
    if (tag.id === Number(term_id)) {
        console.log('match found!', tag)
    }
});

const curried = R.curry((termIds, tag) => {
    return R.map(matchId(tag), termIds);
});

const coloredTags = R.map(curried(termIds), tagsList);
console.log('coloredTags', coloredTags)
return tagsList;

So, at the coloredTags line, a tag from the tagsList is passed into the curried(termIds) function. Remember, Ramda functions accept parameters from right to left.

curried(termIds) already has the termIds array preloaded. Next, in the const curried = line, the termIds array and a single tag are passed in. The tag then moves on to the next curried function matchId, while the termIds array is placed in the R.map. Ramda list functions take the Array of data as the right parameter.

Lastly, in matchId, I can perform my check!

https://i.sstatic.net/CCeRA.png


UPDATE

Although the above explanation answered my initial question on how to curry an item from an Array, it led to a bug in my application. Since the termIds array could contain up to 3 items, the coloredTags R.map would run up to 3 times, resulting in duplicate tags in my tagsList.

For completeness, here is how I resolved my issue, in a simpler manner without the need for a double curried function:

const setTagColors = (tagsList, state) => {
    const setBorder = (tag) => {
        if (tag.id === Number(state.term_id_1)) {
            tag.border1 = true;
        } else if (tag.id === Number(state.term_id_2)) {
            tag.border2 = true;
        } else if (tag.id === Number(state.term_id_3)) {
            tag.border3 = true;
        }
        return tag;
    };

    const coloredTags = R.map(setBorder, tagsList);

    return state.term_id_1 ? coloredTags : tagsList;
};

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

Looking out for JavaScript errors using Selenium?

Currently, I am utilizing Selenium through Python and employing the web driver with the Chrome backend. My goal is to verify that at the completion of each test there were no JavaScript exceptions thrown throughout the execution -- essentially mimicking t ...

What could be causing the child view to not display the AJAX result?

An AJAX call is being made in the following manner: @Ajax.ActionLink("My Schedule", "GetSchedule", "Schedule", new { selectedDate = strToday}, new AjaxOptions { UpdateTargetId = "theTimes", InsertionMode = InsertionMode.Replace, HttpMethod = "GET" }) Th ...

Is your data coming in as NaN?

I am currently developing a basic webpage that has the capability to calculate your stake and determine your return, reminiscent of a traditional betting shop. As of now, I have successfully hard coded the odds into my page. However, while testing my code ...

Vibrant DT data table featuring vertical radio buttons

I am in need of a polished DT datatable that includes radio buttons embedded within a column. While this application provides a solution for horizontal buttons, I have taken on the task of adapting it for a vertical layout. Modifying the matrix was a strai ...

The AJAX call was successful with a return code of 200, however an error

HTML code snippet: <a href="javascript:void(0)" onclick="$.join_group(<?=$USER_ID?>, <?=$groups[$i]["id"]?>)"><?=$language["join"]?></a> JavaScript function: $.join_group = function(user_id, group_id) { var input = "u ...

Manipulate CSS Properties with Javascript Based on Dropdown Selection

I am currently working on implementing a feature that involves changing the CSS property visibility: of an <input> element using a JavaScript function triggered by user selection in a <select> dropdown. Here's what I have so far in my cod ...

steps to eliminate a cookie upon second click

I have successfully implemented a feature where the color of a button is stored in a cookie, so that when the button is clicked, the CSS color remains even after page refresh. However, I am struggling to figure out how to destroy the cookie after the secon ...

The PureComponent FlatList does not refresh properly even after including extraData={this.state} as a prop

After conducting some research, I discovered that using a PureComponent instead of a regular Component can enhance the performance of my FlatList. By doing so, only the row that was changed will be re-rendered rather than the entire list. However, I encoun ...

Issue with ExpressJS Twig module: inability to execute async functions even after adjusting settings as needed

Currently, I am facing an issue while trying to load an array from mongoose into a twig rendered list. An error message keeps popping up: TwigException: You are using Twig.js in sync mode in combination with async extensions. I have made sure to care ...

Issue encountered when trying to retrieve a database variable from a mapReduce operation in MongoDB

Greetings! I am currently developing an application that utilizes a MongoDB database. Within this database, there exists a user collection where all user data is stored. The structure of a document in this collection is as follows: { "_id" : ObjectId( ...

Text below a stationary header

I need some help with my code using material-ui-next beta.30. The issue I am facing is that the content within mui.Paper is appearing behind the AppBar instead of below it. Here's my current setup: import * as React from 'react'; import * a ...

React Container failing to Re-Render despite Redux State Change

I have encountered an issue while working on Redux and React. I am developing a book list where clicking on a book will display its details. Upon selecting a book, the action is properly handled and the state is updated as expected. // reducer_active_boo ...

Escaping the setTimeout loop

I'm struggling to find a solution for breaking out of a setTimeout loop. for (var i = 0; i < 75; i++) { setTimeout(function (i) { return function () { console.log("turn no. " + i); if (table.game.playerWon) { con ...

I'm having trouble making a Javascript ajax request to my Web API controller page. It seems like I just can't figure out the correct URL

Currently, I am facing an issue with my registration page where I am attempting to save input fields into a new record in the Users table. <button class="btn-u" type="submit" onclick="submitclicked()">Register</button> The click event trigger ...

Enabling Multi-Row Form Submission in jQuery: Ensure Submit Button is Disabled Until Every Row Has a Checked

I am dealing with a multi-row form that contains single choice radio buttons in each row. My goal is to have the final <button> tag disabled until a radio button has been checked in each row. Although I have found a solution from a previous question ...

Higher Order Component for JSX element - displaying JSX with wrapped component

I am looking to utilize a ReactJS HOC in order to implement a tooltip around JSX content. The function call should look similar to this: withTooltip(JSX, "very nice") To achieve this, I have created the following function: import React from "re ...

What is the best way to use element.appendChild to generate a link?

I am currently utilizing the following snippet of Javascript to extract information from the current webpage using a browser extension. I have only included a portion of the code that is relevant, as the full script is quite lengthy. The code works perfect ...

Error encountered in jQuery call during Page_Load

Here is the code I am using to register a javascript function on Page_Load (I also tried it on Page_Init). This javascript function switches two panels from hidden to shown based on a parameter when the page loads: protected void Page_Load(object sen ...

JavaScript - Error encountered when accessing information from elements in the DOM

Just started learning javascript and encountering a problem that I can't seem to solve. I'm attempting to assign the className of a <div> element to a variable, but I keep receiving this error message: scripts.js:30 Uncaught TypeError: Can ...

Enhancing and modifying arrays within MongoDB documents

I am attempting to modify the embedded array within a document in a collection. Here is the current structure: { id: 1, fields:[ { "lang" : "eng","embeddedArray" : ["A","B","C"] ...