0

Is it possible to sort through an array based off a format?

I was looking through Array methods and didn't find one.

I have an array of all strings which may or may not contain phone numbers.
The format of the phone numbers are either (877) 843-2900 or 877-843-2900.

I'm trying to get the index of each string in the array which contains a phone number.

For example:

// Example input:
[
  'Call today! Reach us at 314-867-5309 any day of the week.',
  'Over 3,148,675,309 people trust ACME for all their road runner needs!',
  '(877) 843-2900',
  // ...
];

// Example output:
[0, 2, /* ... */];

This is my attempt:

var regex1 = RegExp('/^[\+]?[(]?[0-9]{3}[)]?[-\s\.]?[0-9]{3}[-\s\.]?[0-9]{4,6}$/im','g');

var str1 = 'table football, foosball, (123) 456-7890, 123-456-7890';
var array1;

while ((array1 = regex1.exec(str1)) !== null) {
  console.log(`Found ${array1[0]}. Next starts at ${regex1.lastIndex}.`);

}
4
  • 1
    You have to try something... Otherwise we don't know which part you're having trouble with since this is pretty simple. You cannot ask us to write code for you. You can combine map and regex.exec Commented Dec 17, 2018 at 0:15
  • 2
    research for "phone regex" Commented Dec 17, 2018 at 0:15
  • @johnSmith Here's a link. It contains an explanation and all :) Commented Dec 17, 2018 at 0:26
  • The regex solution has already been provided and will work... The only issue is what if in the future you try to add not just US numbers but let's say French or Australian or... The regex can get out of hand with a lot of edge cases... In these cases, the usual recommended solution is using a dedicated lib like this one from google: github.com/googlei18n/libphonenumber Commented Dec 17, 2018 at 0:39

2 Answers 2

2

Use a regex and a reduce. Start with an empty accumulator and if the regex matches then spread the existing indexes into a new array with the new index else just return the existing indexes.

I took the regex from the comment from @Tico above as the one I was using didn't find them all.

const indexes = [
    'Call today! Reach us at 314-867-5309 any day of the week.',
    'Over 3,148,675,309 people trust ACME for all their road runner needs!',
    '(877) 843-2900'
  ].reduce(
    (indexes, current, index) =>
      /(?:\d{1}\s)?\(?(\d{3})\)?-?\s?(\d{3})-?\s?(\d{4})/g.test(current) ? [...indexes, index] : indexes,
    []
  );

console.log(indexes);

Reduce takes a function and an optional starting accumulator as the parameters.

The function

(indexes, current, index) => /(?:\d{1}\s)?\(?(\d{3})\)?-?\s?(\d{3})-?\s?(\d{4})/g.test(current) ? [...indexes, index] : indexes

takes the parameters, indexes is the accumulator that has collected the indexes that match, current is the current item and index is the index of the current item. It returns a ternary that tests the regex and either returns the existing indexes if it doesn't match or spreads the existing elements into a new array with the current index if it does match.

[]

Is the starting accumulator to hold the indexes.

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

2 Comments

Thank you, this will get me on the right track, what does [...indexes, index] : indexes, []); mean?
[...indexes, index] ... is the spread operator, it spreads the contents of an array into a new array then adds the new index to the end. : is the separator between the two return elements of the ternary operator as it returns [...indexes, index] for a match and indexes if not. [] is the starting operator for the reduce statement that is an empty array.
1

If you know that the phone numbers are either of these two formats: (877) 843-2900 or 877-843-2900, then you can make a naïve regex to match:

(\([0-9]{3}\) |[0-9]{3}-)[0-9]{3}-[0-9]{4}

But this will not recognise phone numbers of any other format.

If you want to match any phone number, you should use a proper library like libphonenumber.


Anyway, assuming you go the naive regex route, we can use Array#reduce to create a new array of indices from the input array of strings:

var strings = 
[
  'Call today! Reach us at 314-867-5309 any day of the week.',
  'Over 3,148,675,309 people trust ACME for all their road runner needs!',
  '(877) 843-2900'
];

var phoneNumbers = strings.reduce(function (indices, currentString, currentIndex) {
  if (/(\([0-9]{3}\) |[0-9]{3}-)[0-9]{3}-[0-9]{4}/.test(currentString)) {
    indices.push(currentIndex);
  }
  return indices;
}, []);

console.log(phoneNumbers);

Comments

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.