omygoodness
omygoodness

Reputation: 365

Ramda - How to filter array with other array and multiple properties

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

Upvotes: 0

Views: 525

Answers (1)

Ori Drori
Ori Drori

Reputation: 192422

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>

Upvotes: 1

Related Questions