0

I am trying to filter one array with another array using Ramda.

This is an array of edges for ELK algorithm. sources and targets are arrays but in this case, those arrays have always single value.

const edges = [
    {
        "id": "47c0ffd2-6a2c-4e7f-9fd9-0e1207225ada#2789a940-15d1-4ff0-b2ef-9f6cde676c18",
        "sources": [
            "47c0ffd2-6a2c-4e7f-9fd9-0e1207225ada"
        ],
        "targets": [
            "2789a940-15d1-4ff0-b2ef-9f6cde676c18"
        ]
    },
    {
        "id": "47c0ffd2-6a2c-4e7f-9fd9-0e1207225ada#7cf88eab-5da4-492b-839c-30916fa98fb9",
        "sources": [
            "47c0ffd2-6a2c-4e7f-9fd9-0e1207225ada"
        ],
        "targets": [
            "7cf88eab-5da4-492b-839c-30916fa98fb9"
        ]
    },
    {
        "id": "fefd95e0-11d0-44f6-9b48-ec2a0ea1b328#53a6d558-c97b-42df-af69-cf27912dd158",
        "sources": [
            "fefd95e0-11d0-44f6-9b48-ec2a0ea1b328"
        ],
        "targets": [
            "53a6d558-c97b-42df-af69-cf27912dd158"
        ]
    }
]

This is an example of a second array that I would like to use to filter values from the first one - id corresponds to the value in sources and outgoingNodeId corresponds to the value in targets from the first array.

const selectedNodes = [
    {
        "id": "47c0ffd2-6a2c-4e7f-9fd9-0e1207225ada",
        "outgoingNodeId": "2789a940-15d1-4ff0-b2ef-9f6cde676c18",
        "groupId": "27",
        "sectionId": "0e09e7dd-0f71-48a1-a843-36d8e85574b3"
    },
    {
        "id": "fefd95e0-11d0-44f6-9b48-ec2a0ea1b328",
        "outgoingNodeId": "53a6d558-c97b-42df-af69-cf27912dd158",
        "groupId": "27",
        "sectionId": "0e09e7dd-0f71-48a1-a843-36d8e85574b3"
    }
]

In this case, result should look like this:

const result = [
    {
        "id": "47c0ffd2-6a2c-4e7f-9fd9-0e1207225ada#2789a940-15d1-4ff0-b2ef-9f6cde676c18",
        "sources": [
            "47c0ffd2-6a2c-4e7f-9fd9-0e1207225ada"
        ],
        "targets": [
            "2789a940-15d1-4ff0-b2ef-9f6cde676c18"
        ]
    },
    {
        "id": "fefd95e0-11d0-44f6-9b48-ec2a0ea1b328#53a6d558-c97b-42df-af69-cf27912dd158",
        "sources": [
            "fefd95e0-11d0-44f6-9b48-ec2a0ea1b328"
        ],
        "targets": [
            "53a6d558-c97b-42df-af69-cf27912dd158"
        ]
    }
] 

I tried few things but to be honest I don't have anything worth showing here.

My last try was around:

R.pipe(
  R.groupBy(R.prop('sources'))
)(edges)

And then filtering using R.filter(R.compose(R.flip(R.contains)(selectedNodesIds), R.prop('id')))

But I need to filter not only sources but also targets

Any help would be appreciated. Thank you

EDIT: Another example for a different approach:

const edges = [
    {
        "id": "47c0ffd2-6a2c-4e7f-9fd9-0e1207225ada#2789a940-15d1-4ff0-b2ef-9f6cde676c18",
        "sources": [
            "47c0ffd2-6a2c-4e7f-9fd9-0e1207225ada"
        ],
        "targets": [
            "2789a940-15d1-4ff0-b2ef-9f6cde676c18"
        ]
    },
    {
        "id": "47c0ffd2-6a2c-4e7f-9fd9-0e1207225ada#7cf88eab-5da4-492b-839c-30916fa98fb9",
        "sources": [
            "47c0ffd2-6a2c-4e7f-9fd9-0e1207225ada"
        ],
        "targets": [
            "7cf88eab-5da4-492b-839c-30916fa98fb9"
        ]
    },
    {
        "id": "fefd95e0-11d0-44f6-9b48-ec2a0ea1b328#53a6d558-c97b-42df-af69-cf27912dd158",
        "sources": [
            "fefd95e0-11d0-44f6-9b48-ec2a0ea1b328"
        ],
        "targets": [
            "53a6d558-c97b-42df-af69-cf27912dd158"
        ]
    },
    ...multipleObjectsHere
]

selectedNodes contains only one object:

const selectedNodes = [
    {
        "id": "47c0ffd2-6a2c-4e7f-9fd9-0e1207225ada",
        "outgoingNodeId": "2789a940-15d1-4ff0-b2ef-9f6cde676c18",
        "groupId": "27",
        "sectionId": "0e09e7dd-0f71-48a1-a843-36d8e85574b3"
    }
]

As a result, we get:

const result = [
    {
        "id": "47c0ffd2-6a2c-4e7f-9fd9-0e1207225ada#2789a940-15d1-4ff0-b2ef-9f6cde676c18",
        "sources": [
            "47c0ffd2-6a2c-4e7f-9fd9-0e1207225ada"
        ],
        "targets": [
            "2789a940-15d1-4ff0-b2ef-9f6cde676c18"
        ]
    },
    {
        "id": "fefd95e0-11d0-44f6-9b48-ec2a0ea1b328#53a6d558-c97b-42df-af69-cf27912dd158",
        "sources": [
            "fefd95e0-11d0-44f6-9b48-ec2a0ea1b328"
        ],
        "targets": [
            "53a6d558-c97b-42df-af69-cf27912dd158"
        ]
    },
    ...multipleObjectsHere
] 

To sum up, if something is not in selectedNodes we don't filter it out and leave it as a result

1 Answer 1

1

Use R.innerJoin to create an intersection between 2 arrays using a comparison function:

const { innerJoin, includes } = R

const fn = innerJoin(({ sources, targets }, { id, outgoingNodeId }) => 
  includes(id, sources) && includes(outgoingNodeId, targets)
)

const edges = [{"id":"47c0ffd2-6a2c-4e7f-9fd9-0e1207225ada#2789a940-15d1-4ff0-b2ef-9f6cde676c18","sources":["47c0ffd2-6a2c-4e7f-9fd9-0e1207225ada"],"targets":["2789a940-15d1-4ff0-b2ef-9f6cde676c18"]},{"id":"47c0ffd2-6a2c-4e7f-9fd9-0e1207225ada#7cf88eab-5da4-492b-839c-30916fa98fb9","sources":["47c0ffd2-6a2c-4e7f-9fd9-0e1207225ada"],"targets":["7cf88eab-5da4-492b-839c-30916fa98fb9"]},{"id":"fefd95e0-11d0-44f6-9b48-ec2a0ea1b328#53a6d558-c97b-42df-af69-cf27912dd158","sources":["fefd95e0-11d0-44f6-9b48-ec2a0ea1b328"],"targets":["53a6d558-c97b-42df-af69-cf27912dd158"]}]
const selectedNodes = [{"id":"47c0ffd2-6a2c-4e7f-9fd9-0e1207225ada","outgoingNodeId":"2789a940-15d1-4ff0-b2ef-9f6cde676c18","groupId":"27","sectionId":"0e09e7dd-0f71-48a1-a843-36d8e85574b3"},{"id":"fefd95e0-11d0-44f6-9b48-ec2a0ea1b328","outgoingNodeId":"53a6d558-c97b-42df-af69-cf27912dd158","groupId":"27","sectionId":"0e09e7dd-0f71-48a1-a843-36d8e85574b3"}]

const result = fn(edges, selectedNodes)

console.log(result)
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.28.0/ramda.min.js" integrity="sha512-t0vPcE8ynwIFovsylwUuLPIbdhDj6fav2prN9fEu/VYBupsmrmk9x43Hvnt+Mgn2h5YPSJOk7PMo9zIeGedD1A==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>

The other logic should be see if the id is included in sources. If it is also check the outgoingNodeId. If not, return true.

const { innerJoin, includes } = R

const fn = innerJoin(({ sources, targets }, { id, outgoingNodeId }) => 
  !includes(id, sources) || includes(outgoingNodeId, targets)
)

const edges = [{"id":"47c0ffd2-6a2c-4e7f-9fd9-0e1207225ada#2789a940-15d1-4ff0-b2ef-9f6cde676c18","sources":["47c0ffd2-6a2c-4e7f-9fd9-0e1207225ada"],"targets":["2789a940-15d1-4ff0-b2ef-9f6cde676c18"]},{"id":"47c0ffd2-6a2c-4e7f-9fd9-0e1207225ada#7cf88eab-5da4-492b-839c-30916fa98fb9","sources":["47c0ffd2-6a2c-4e7f-9fd9-0e1207225ada"],"targets":["7cf88eab-5da4-492b-839c-30916fa98fb9"]},{"id":"fefd95e0-11d0-44f6-9b48-ec2a0ea1b328#53a6d558-c97b-42df-af69-cf27912dd158","sources":["fefd95e0-11d0-44f6-9b48-ec2a0ea1b328"],"targets":["53a6d558-c97b-42df-af69-cf27912dd158"]}]
const selectedNodes = [{"id":"47c0ffd2-6a2c-4e7f-9fd9-0e1207225ada","outgoingNodeId":"2789a940-15d1-4ff0-b2ef-9f6cde676c18","groupId":"27","sectionId":"0e09e7dd-0f71-48a1-a843-36d8e85574b3"}]

const result = fn(edges, selectedNodes)

console.log(result)
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.28.0/ramda.min.js" integrity="sha512-t0vPcE8ynwIFovsylwUuLPIbdhDj6fav2prN9fEu/VYBupsmrmk9x43Hvnt+Mgn2h5YPSJOk7PMo9zIeGedD1A==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>

Sign up to request clarification or add additional context in comments.

3 Comments

Thank you. Working as expected like always :) Can you help me with one adjustment? Because I tested it and apparently didn't think this through. 1. Filter out values with same id - sources, outgoingNodeId - targets exactly like right now 2. But leave all other values unfiltered. For example, if selectedNodes contains only one value we should filter only objects with the same sources, targets and leave all other values unfiltered and add them as part of result. Is it possible?
Please add an example
I added another example. Hope it explains it better. Basically, if something is in selectedNodes we should filter it and leave the rest of edges untouched

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.