0

I have an array containing a list of filenames:

var files = ['home_01.ai','home_02.ai','home_03.ai','imprint_01.ai','imprint_02.ai']

What I want to do is reorganise this array into a multi-dimensional array that groups together each file with the same prefix. In this case:

var firstArray = ['home_01.ai','home_02.ai','home_03.ai'], /*home*/
    secondArray = ['imprint_01.ai','imprint_02.ai']; /*imprint*/

How could I achieve that when there can be a variable amount of prefixes that can be any length in my file array?

5 Answers 5

1

You can loop over the array and split the filename on '_' to get the prifix, then it is a case of adding those filenames into the right array, indexed by prefix.

var files = ['home_01.ai', 'home_02.ai', 'home_03.ai', 'imprint_01.ai', 'imprint_02.ai'];
var result = {};

for (var i = 0; i < files.length; i++) {
  if (files[i].indexOf('_') < 0) 
  {
    console.log("No prefix detected in '" + files[i] + "'.");
    continue;
  }
  var prefix = files[i].split('_')[0];
  if (!result[prefix])
    result[prefix] = [];
  result[prefix].push(files[i]);
}

console.log(result);

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

2 Comments

thanks four your reply. That's exactly what I wanted to know. But I don't get the last part in the lopp " if (!result[prefix])... " ..why don't you open the if() with the brackets {} ? .. sorry for being nooby..
If the code that would be inside a block such as an if, for, while only has one line, you can skip the brackets. Note that you can't do this for functions, or object declarations, or try-catch statements.
0

You can do it with AlaSQL JavaScript data processing library.

Here is the solution for your problem:

var res = alasql('COLUMN OF SELECT ARRAY(_) FROM ? \
     GROUP BY _->split("_")->0',[files]);

This statement returns array of arrays grouped by prefix:

[ [ 'home_01.ai', 'home_02.ai', 'home_03.ai' ],
  [ 'imprint_01.ai', 'imprint_02.ai' ] ]

Here:

  • COLUMN OF - return only first column of query
  • SELECT ... FROM ? GROUP BY ... - select statement
  • ARRAY(_) - group records in array
  • FROM ? - query from parameter [files]
  • GROUP BY ->split("")->0 - take a value, split it with '' and then take first element of array (similar to JS r.split('')[0]

Disclaimer: I am an author of AlaSQL.

3 Comments

AlaSQL is good library but he don't have to use a full library for just this problem.
1 line source code vs more than 10. That is why we do need libraries :)
Right. I would have used the library, but not in Web projects where bandwidth is important. For Nodejs, yes. I already cloned for it :) @agershun
0

UPDATE

I missed that you may have another prefixes. Updated for using with any prefix.

function splitFilesIntoTypes(_files, cb) {
  var result = [];
  // loop through the array
  _files.map(function(a, b){
      if(!result[a.split('_')[0]])
        result[a.split('_')[0]] = [];
    
      result[a.split('_')[0]].push(a);
  });
  return result
}

var files = ['another_01.ai','home_01.ai','home_02.ai','home_03.ai','imprint_01.ai','imprint_02.ai'];
console.log(splitFilesIntoTypes(files));

FIXED

Supposing you have only two types of names (home_... and imprint_...). I made this function to split it into two arrays.

// function takes array and returns two array to callback function
function splitFilesIntoTypes(_files, cb) {
  // if you have only two types of names
  var _home = [], _imprint = [];

  // loop through the array
  _files.map(function(a, b){
      
      if(a.split('_')[0] === 'home') _home.push(a);
      if(a.split('_')[0] === 'imprint') _imprint.push(a);
  });
  
  if(typeof cb === "function")
    cb(_home, _imprint);
  

}

var files = ['home_01.ai','home_02.ai','home_03.ai','imprint_01.ai','imprint_02.ai'];

splitFilesIntoTypes(files, function(firstArray, secondArray) {

  console.log(firstArray);
  console.log(secondArray);
  
});

2 Comments

The question specifies that there can be any number of different prefixes in the files array.
Your answer is hard coded to two prefixes. The code has to change if the data changes.
0

var files = ['home_01.ai', 'home_02.ai', 'home_03.ai', 'imprint_01.ai', 'imprint_02.ai'];
var result = files.reduce(function(prev, curr) {
  var index = curr.indexOf('_01.');
  if (index !== -1) {
    prev.push(index);
  }
  return prev;
}, []).map(function(index) {
  return files.splice(0, index - 1);
});


document.body.textContent = JSON.stringify(result);

Please note that this answer assumes that files are already alphabetically sorted.

Comments

0

I'm using the same approach as Maxali, but using a javascript library called lodash. It's useful for filtering arrays and objects without need to write your own filtering code.

Instead of saving to a 2 dimensional array, I create a JSON object with arrays as the value as I find it useful to have keys I can read and understand in my javascript. Have a look at lodash, it may be overkill for what you need today but could be useful for tomorrow.

https://lodash.com/

<!DOCTYPE html>
<html>

<head>
  <script src="https://raw.github.com/lodash/lodash/4.0.0/dist/lodash.js"></script>
  <!-- downloaded from https://lodash.com -->
  <script>
    var files = ['home_01.ai', 'home_02.ai', 'home_03.ai', 'imprint_01.ai', 'imprint_02.ai'];

    var getPrefixFn = function(file) {
      return file.substr(0, file.indexOf('_'));
    };
    var prefixes = _.map(files, getPrefixFn);
    var uniquePrefixes = _.uniq(prefixes);
    var groupedFiles = {};

    _(files).forEach(function(file) {
      _(uniquePrefixes).forEach(function(prefix) {
        if (groupedFiles[prefix] == null) groupedFiles[prefix] = []; // create a new group if it doesnt exist
        if (file.indexOf(prefix) === 0) {
          groupedFiles[prefix].push(file);
        }
      });
    });

    console.log(groupedFiles);
  </script>

</head>

<body>
</body>

</html>

If a 2 dimensional array is easier to process then try this:

<!DOCTYPE html>
<html>

<head>
  <script src="https://raw.github.com/lodash/lodash/4.0.0/dist/lodash.min.js"></script>
  <!-- downloaded from https://lodash.com -->
  <script>
    var files = ['home_01.ai', 'home_02.ai', 'home_03.ai', 'imprint_01.ai', 'imprint_02.ai'];

    var getPrefixFn = function(file) {
      return file.substr(0, file.indexOf('_'));
    };
    var prefixes = _.map(files, getPrefixFn);
    var uniquePrefixes = _.uniq(prefixes);
    var groupedFiles = [];

    for (var index = 0, length = uniquePrefixes.length; index < length; index += 1) {
      var prefix = uniquePrefixes[index];
      groupedFiles[index] = [];
      for (var fileIndex = 0, fileLength = files.length; fileIndex < fileLength; fileIndex += 1) {
        if (files[fileIndex].indexOf(prefix) === 0) {
          groupedFiles[index].push(files[fileIndex]);
        }
      };
    }

    console.log(groupedFiles);
  </script>
</head>

<body>

</body>

</html>

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.