2

I have 2 arrays:

blockedNumbers: ['123', '456', '789', '247'];
contacts: [
           {name: 'Foo', numbers: [{ home:'123' }, { mobile:'456' }]}, 
           {name: 'Bar', numbers: [{ home:'789' }]}
          ]

I want to create a new array of blocked contacts which will contain:

[
  { name: Foo, numbers: [{ home:'123' }, { mobile:'456' }] }, 
  {name: 'Bar', numbers: [{ home:'789' }]} 
  '247'
]

So the solution I have tried first loops over blocked numbers, then forEach contact, if blocked number in numbers, push to array. But the result turns out as

[
  '123'
  { name: Foo, numbers: ['123', '456'] }, 
  {name: 'Bar', numbers: ['789']} 
  '456'
  '789'
  '247'
]

Code below:

const newBlacklistWithContacts = [];
blockedNumbers.forEach((blockedNumber) => {
    contacts.map((contact) => {
    // if blocked number in contacts
    Object.keys(contact.numbers).forEach((e) => {
    if (contact.numbers[e] === blockedNumber) {
        const alreadyAdded = newBlacklistWithContacts.find(blacklistContact => blacklistContact.name === contact.name);
        if (!alreadyAdded) {
            return newBlacklistWithContacts.push({ name: contact.name, numbers: contact.numbers });
        }
    }
    else if (!newBlacklistWithContacts.includes(blockedNumber)) {
        return newBlacklistWithContacts.push(blockedNumber);
    }
    });
    });
});

I'm sure there is a more efficient way to do this & actually return what I need? (All of the blacklisted contacts and if not in contacts, only the number) I am using js and React.js in this project

2 Answers 2

4

If your data set is really large, you can optimise your algorithm by doing O(1) lookups in a Set instead of using indexOf or includes which do O(n) lookups:

// Input
const blockedNumbers =  ['123', '456', '789', '247'];
const contacts = [{name: 'Foo', numbers: [{ home:'123' }, { mobile:'456' }]}, {name: 'Bar', numbers: [{ home:'789' }]}];

// Algorithm
const set = new Set(blockedNumbers);
const notused = new Set(blockedNumbers);
const newBlacklistWithContacts = contacts.filter(contact => 
    contact.numbers.map(obj => Object.values(obj)[0])
                   .filter(number => set.has(number) && (notused.delete(number) || true)).length
).concat(...notused);

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

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

Comments

0

var blockedNumbers = ['123', '456', '789', '247'];
var contacts = [{
        name: 'Foo',
        numbers: [{
            home: '123'
        }, {
            mobile: '456'
        }]
    },
    {
        name: 'Bar',
        numbers: [{
            home: '789'
        }]
    }
]

var blocks = [];
contacts.forEach(v1 => (v1.numbers.forEach(v2 => {
    blocks.push(Object.values(v2)[0]);
})));
blockedNumbers.forEach(val => (blocks.indexOf(val) == -1 ? contacts.push(val) : null));

console.log(contacts);

1 Comment

Two issues: (1) This mutates the input. (2) This always includes all contacts, not just the blacklisted.

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.