简体   繁体   中英

How to change items in an array using other items in the same array

I need to change array A to be like array B, making sure the hashed item becomes the before of any number of non hashed items, until the next hashed item

const A = [ '# test',
  'test',
  '# layouts',
  'main',
  'nav' ]

const B = ['test/test',
    'layouts/main',
    'layouts/nav' ]

You can use reduce for this, the accumulator should be an object containing two values, the first will be the results array and the other will be the current hash string to be used within reduce to generate the paths. Once reduce finishes its work we can store the result property of the accumulator into our result variable B :

const B = A.reduce((acc, str) => {                           // for each string in the array A
   if(str.indexOf("#") === 0) {                              // if the string is hashed one
      acc.currentHash = str.slice(2);                        // set the current hash to this string
   } else {                                                  // otherwise
      acc.result.push(acc.currentHash + "/" + str);          // use the current hash to generate the resulting string of the current string
   }
   return acc;
}, { result: [], currentHash: ""}).result;                   // once reduce finishes, use '.result' to access the result array of the accumulator

Example:

 const A = [ '# test', 'test', '# layouts', 'main', 'nav' ]; const B = A.reduce((acc, str) => { if(str.indexOf("#") === 0) { acc.currentHash = str.slice(2); } else { acc.result.push(acc.currentHash + "/" + str); } return acc; }, { result: [], currentHash: ""}).result; console.log(B); 

My preferred approach would be to map the array to the desired format and then filter out the extraneous markers.

const needle = '# ';
let directoryName = '';
const b = a.map((elem) => {
    if (elem.startsWith(needle)) {
        directoryName = elem.substring(needle.length);
        return;
    }
    return directoryName + '/' + elem;
}).filter(Boolean);

Note that I have optimized the code for readability. It will loop over the array twice, which is almost certainly fine, since the operations here are very fast. But if you have a huge array and need every bit of performance, Ibrahim's answer would be more appropriate.

Here's an approach you can take that utilizes Array.prototype.reduce and Object.keys

 function modify(a, delimiter) { const f = a.reduce((accum, el) => { var s = el.replace(/\\s/g, ''); if (s.charAt(0) === delimiter) { accum.pointer = s.substring(1); accum.data[accum.pointer] = []; } else { accum.data[accum.pointer].push(el); } return accum; }, { pointer: null, data: {} }); return Object.keys(f.data).map(k => { var s = `${delimiter}${k}` var values = f.data[k]; values.forEach(v => { s += `/${v}` }); return s; }); } const A = ['# test', 'test', '# layouts', 'main', 'nav' ] const B = modify(A, "#"); console.log(B); 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM