Mapping arrays within arrays using functional programming techniques

Imagine you have the following arrays at your disposal:

const array1 = ["a1", "b1", "c1", "d1"],
      array2 = ["a2", "b2"],
      array3 = ["a3", "b3", "c3"]

Do any special functions like ramda exist that can simplify this specific situation, allowing you to work with one or more arrays?

const nestedMap = map => {
    const result = []

    for(let item1 of array1) 
        for(let item2 of array2)
            for(let item3 of array3)
                    result.push(map(item1, item2, item3))
    return result
}

The complete function would look something like this:

// Sample usage
nestedMap((item1, item2, item3) => `${item1} ${item2} ${item3}`, array1, array2, array3)

I'm hoping to find a solution without having to start from scratch.

Note: You don't necessarily need to use ramda; vanilla JavaScript or other libraries are also acceptable. I just mentioned ramda as it has many functions that could potentially help with this issue

Answer №1

If arrays are your thing, then the applicative instance can be your best friend. Utilize R.lift to simplify your function in this scenario:

const array1 = ["a1", "b1", "c1", "d1"],
      array2 = ["a2", "b2"],
      array3 = ["a3", "b3", "c3"]

const nestedMap = R.lift((item1, item2, item3) => `${item1} ${item2} ${item3}`)

console.log(nestedMap(array1, array2, array3)
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.min.js"></script>

Answer №2

When working with Ramda, you have access to the xprod function which can provide the cross-product of two lists. With a little tweaking, it's possible to extend this functionality to handle multiple lists like so:

const xproduct = R.reduce(R.pipe(R.xprod, R.map(R.unnest)), [[]])

This allows for the creation of a nested map function with relative ease:

const array1 = ["a1", "b1", "c1", "d1"],
      array2 = ["a2", "b2"],
      array3 = ["a3", "b3", "c3"]

const xproduct = R.reduce(R.pipe(R.xprod, R.map(R.unnest)), [[]])
const nestedMap = (fn, ...arrs) => R.map(R.apply(fn), xproduct(arrs))

console.log(nestedMap((a, b, c) => `${a}-${b}-${c}`, array1, array2, array3))
//==> ["a1-a2-a3", "a1-a2-b3", ...]
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.min.js"></script>

Answer №3

One way to tackle this is by following a two-step method:

  1. First, assemble all the products
  2. Next, execute the function mapping process.

const
    nestedMap = (fn, ...array) => array
        .reduce((a, b) => a.reduce((r, v) => r.concat(b.map(w => [].concat(v, w))), []))
        .map(a => fn(...a)),
    array1 = ["a1", "b1", "c1", "d1"],
    array2 = ["a2", "b2"],
    array3 = ["a3", "b3", "c3"],
    result = nestedMap((item1, item2, item3) => `${item1} ${item2} ${item3}`, array1, array2, array3)

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Answer №4

Understanding the Implementation

This detailed explanation sheds light on how @ScottChristopher's response functions by showcasing the direct implementation of .ap (and .chain) on the prototype of Array – presented as a learning exercise! No need to panic, even for those obsessed with prototypes...

The main objective here is to illustrate the expected behavior/output using a code snippet that encapsulates all components at once. With just around ~8 lines of code to grasp, the complexity level is minimal; especially when compared to delving into the Rambda source code (which is actually quite neat).

I recently posted another answer that undertakes a similar approach utilizing delimited continuations – if you find this response intriguing, I believe you will also derive enjoyment from exploring that one ^_^

// Array Applicative  
Array.prototype.ap = function (...args)
  {
    const loop = (acc, [x,...xs]) =>
      x === undefined
        ? [ this [0] (...acc) ]
        : x.chain (a =>
            loop (acc.concat ([a]), xs))
    return loop ([], args)
  }
 
// Array Monad
Array.prototype.chain = function chain (f)
  {
    return this.reduce ((acc, x) =>
      acc.concat (f (x)), [])
  }

const array1 = ['a1', 'b1', 'c1', 'd1']
const array2 = ['a2', 'b2']
const array3 = ['a3', 'b3', 'c3']

console.log ([ (x,y,z) => [x,y,z] ] .ap (array1, array2, array3))
// [ [ 'a1', 'a2', 'a3' ],
//   [ 'a1', 'a2', 'b3' ],
//   [ 'a1', 'a2', 'c3' ],
//   [ 'a1', 'b2', 'a3' ],
//   [ 'a1', 'b2', 'b3' ],
//   [ 'a1', 'b2', 'c3' ],
//   [ 'b1', 'a2', 'a3' ],
//   [ 'b1', 'a2', 'b3' ],
//   [ 'b1', 'a2', 'c3' ],
//   [ 'b1', 'b2', 'a3' ],
//   [ 'b1', 'b2', 'b3' ],
//   [ 'b1', 'b2', 'c3' ],
//   [ 'c1', 'a2', 'a3' ],
//   [ 'c1', 'a2', 'b3' ],
//   [ 'c1', 'a2', 'c3' ],
//   [ 'c1', 'b2', 'a3' ],
//   [ 'c1', 'b2', 'b3' ],
//   [ 'c1', 'b2', 'c3' ],
//   [ 'd1', 'a2', 'a3' ],
//   [ 'd1', 'a2', 'b3' ],
//   [ 'd1', 'a2', 'c3' ],
//   [ 'd1', 'b2', 'a3' ],
//   [ 'd1', 'b2', 'b3' ],
//   [ 'd1', 'b2', 'c3' ] ]

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

Can you modify a attribute value in one HTML file from another?

I currently have a website and I am looking to modify the aria-expanded value of an expandable paragraph on another page when I click on an anchor element in the main page. What changes do I need to make in my main.html file in order to update the aria-exp ...

Passing data from parent component to child component in React

For my static website using React or Gatsby, I need to pass a prop or boolean variable from subpages to the main layout component in order to determine whether to display a Hero image. Here is a simplified version of the code for the page: import React f ...

DxDataGrid: Implementing a comprehensive validation system for multiple edit fields

I'm currently working with a DxDataGrid within an Angular Application. Within this particular application, I have the need to input four dates. I've implemented validation rules that work well for each individual field. However, my challenge aris ...

A streamlined approach for tallying the total number of swaps needed to insertion sort an array of integers in ascending order

Is it possible to determine the number of swaps required by insertion sort to sort an array of length n in less than O(n2) time? For instance: arr[]={2 ,1, 3, 1, 2}; // The answer is 4. Procedure: for i <- 2 to N j <- i while j > 1 and ...

Tips for Wrapping Page Layouts and Routes in Angular 4

As I work with my regular angular 4 app, I often find myself using Router, ActivatedRoute.params.subscribe, [routerLink], and other tools to navigate between pages and interpret URLs. This results in a multitude of "magic strings" scattered throughout var ...

Retrieve values from an array of variables based on the values of a different variable

Imagine I have this dataset: structure(list(AccountNumber = 1:5, ActivationDate = c(201001L, 201002L, 201001L, 201010L, 201008L), Payments_201001 = c(100L, NA, 2342L, NA, NA), Payments_201002 = c(200L, 100L, 235L, NA, NA), Payments_201003 = c(100L, 100 ...

What is the process for closing a bootstrap modal once a form has been submitted successfully?

I'm currently learning HTML, CSS, JS, and PHP and challenging myself to create a webpage that allows users to leave messages. However, I'm facing difficulty implementing a functionality that automatically closes the modal after the user submits t ...

Monitor and retrieve live updates of links using Javascript

I am a beginner in JavaScript and recently developed a successful Chrome extension for Dubtrack. I have been struggling to find a way to make my injected script run in real-time and grab the latest YouTube music video URL. Any assistance would be greatly a ...

Getting the string value from a table row using JavaScript

I need to capture the value of result_status from the row labeled status. If all values in the row labeled status are 'pass', then the result_status will also be 'pass'. However, if any one of the values in the row labeled status is &a ...

Encountering a "require is not defined" error when trying to launch a Selenium

I have developed a basic selenium application and now I am looking to implement a graphical user interface for it. Here is the code snippet: index.html: <html> <head> <meta charset="UTF-8" /> <title>Selenium Ap ...

Is there a way to completely define CSS animation using only JavaScript?

I am looking to implement CSS animation on HTML elements that are generated entirely through a JavaScript function. The approach I am taking involves customizing settings and functions for each part of the animation, which is why this method is necessary. ...

Utilize Bootstrap v4.6 to control the visibility of navigation pills based on specific times of the day using JavaScript

My webpage contains two nav-pills that I want to hide during certain hours of the day and then make visible again later on. However, there is a third nav-pill that should remain unaffected and be visible at all times. function showNavPill() { let now = ne ...

Experiencing a problem with the localhost connection

I've been trying to work on this issue using React and local host, but it keeps showing the direct file instead of the website. I've been stuck on this problem for the past 3-4 hours and still haven't been able to find a solution. I'm h ...

Displaying all divs when the checkboxes are unchecked

My code displays a product list with various details stored in different divs based on data attributes like brand, store, and more. A friend helped me develop a filter using checkboxes for record selection. However, I need to make a small modification to i ...

Clearing input fields after entering information

Is there a way to automatically assign the value from a scanner input to a variable in an input box and clear it for the next input? HTML <ion-view hide-nav-bar="true"> <ion-content class="padding"><br> <label class="item item ...

Is there a way to deactivate an ng-click function once it has been triggered within an ng-if ng-switch block?

Whenever a user clicks on the flag button, it flags the discussion and then the button changes to display 'successfully flagged'. I am currently facing an issue with disabling the ng-click after clicking the flag button. The ng-click still works ...

Enable Intellisense for my custom ES6 JavaScript modules in VS Code

Using VS Code Intellisense can greatly enhance productivity when working with internal project files, providing helpful autocompletion features and utilizing written JSDoc comments. However, my current projects involve custom JavaScript libraries stored i ...

Is it possible to create a popup window that remains fixed at the top edge of the screen but scrolls along with the rest of the page if

In an attempt to organize my thoughts, I am facing a challenge with a search page similar to Google. The search results trigger a popup window when hovering over an icon, located to the right of the search results. Here is what I am looking to achieve with ...

Retrieve Static Property Values Using jQuery/JavaScript in Backend Code

My challenge is to fetch the Max value and Percent value into a jQuery function. I attempted to retrieve these values using hidden variables and Session variables on page load, but they always return 0. Here are the properties: public static int Max { ...

JavaScript Scrolling Functionality Not Functioning as Expected

I have implemented a scroll function on my website $('#lisr').scroll( function() { if($(this).scrollTop() + $(this).innerHeight()>= $(this)[0].scrollHeight) { //Perform some action here } } However, I am encountering an ...