0

The following function matches the strings in a file (queries) with the strings of another two files (archives). I included the important logs:

console.log('q:', queries)
console.log('a:', archives)
queries.forEach(query => {
  const regex = new RegExp(query.trim(), 'g')
  archives.forEach(archive => {
    const matched = archive.match(regex)
    console.log('m:', matched)
  })
})

q: [ 'one two', 'three four\n' ]
a: [ 'one two three four three four\n', 'one two three four\n' ]
m: [ 'one two' ]
m: [ 'one two' ]
m: [ 'three four', 'three four' ]
m: [ 'three four' ]

How to modify the code so I merge matched and end up with a result like this?

r1: [ 'one two',  'one two' ]
r2: [ 'three four', 'three four', 'three four' ]

(Maybe I can use .reduce but I'm not very sure how.)

EDIT: I tried this:

  const result = matched.reduce(function (a, b) {
    return a.concat(b)
  }, [])

But ended up with the same result.

2
  • what is the input? why two outputs? Commented Nov 29, 2016 at 14:53
  • the input is what you see in q: and a:. I want an array for each repeated string. Commented Nov 29, 2016 at 14:55

3 Answers 3

1

This should do it:

var queries = [ 'one two', 'three four\n' ],
    archives = [ 'one two three four three four\n', 'one two three four\n' ],
    results = {};

queries.forEach(query => {
  const regex = new RegExp(query.trim(), 'g')
  archives.forEach(archive => {
    const matched = archive.match(regex)
    results[matched[0]] = (results[matched[0]] || []).concat(matched) || matched;
  })
})

console.log(results)

Store the results in an object, using the found string as a key.

For some cleaner data, you can just get the match counts, as fafl suggested:

var queries = [ 'one two', 'three four\n' ],
    archives = [ 'one two three four three four\n', 'one two three four\n' ],
    results = {};

queries.forEach(query => {
  const regex = new RegExp(query.trim(), 'g')
  archives.forEach(archive => {
    const matched = archive.match(regex)
    results[matched[0]] = (results[matched[0]] || 0) + matched.length
  })
})

console.log(results)

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

3 Comments

Strange, the result seems a bit different for me: { 'one two': [ 'one two', 'one two' ] } { 'three four': [ 'three four', 'three four', 'three four' ] }
@alex: Yes, it generates a single object. This is easier to work with than separate variables.
When you're already changing the result, just store the count instead: {"one two": 2, "three four": 3}
1
let queries = [ 'one two', 'three four\n' ],
    archives = [ 'one two three four three four\n', 'one two three four\n' ]

queries.forEach(query => {
  let regex = new RegExp(query.trim(), 'g')

  // first, you need to collect the matched result into a new array
  // forEach will do the process you specified, but won't return any value
  // "map" is the better choice, as it will return the process result
  let result = archives.map(archive => {

    return archive.match(regex)

    // now you could reduce against the new array
  }).reduce(function(a, b) {
    return a.concat(b); 
  }, [])

  console.log(result)

})

One more thing, I don't see "const" will do anything good here, it just let think about why it has to be something unchangeable. So "let" is better to use for reduce the confusion.

Comments

1

You don't need reduce for this:

var flatten = arr => [].concat.apply([], arr)
queries.map(q =>
  flatten(
    archives.map(a =>
      a.match((new RegExp(q.trim(), 'g')))
    )
  )
)

1 Comment

[].concat.apply([], arr) is used to flatten a 2D array. I don't think there is a better way that involves spread. I changed my answer to be a bit more readable.

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.