1 Востаннє редагувалося Tar (04.05.2018 16:45:49)

Тема: Чи можливий такий варіант розв`язку задачі.

Початківець.
Намагався вирішити самостійно, на перший погляд працює.
Цікавить думка форумчан чи такий варіант розв`язку можливий.

Умова задачі.
Розробити функцію file_search(folder, filename),
яка приймає 2 аргументи -- список folder та рядок filename,
та повертає рядок -- повний шлях до файлу або папки filename в структурі folder.

Файлова структура folder задається наступним чином:

Список -- це папка з файлами, його 0-й елемент містить назву папки, а всі інші можуть представляти або файли в цій папці (1 файл = 1 рядок-елемент списку), або вкладені папки, які так само представляються списками. Як і в файловій системі вашого комп'ютера, шлях до файлу складається з імен всіх папок, в яких він міститься, в порядку вкладеності (починаючи з зовнішньої і до папки, в якій безпосередньо знаходиться файл), розділених "/".

Вважати, що імена всіх файлів є унікальними. Повернути логічне значення False, якщо файл не знайдено.

Наприклад
Виклик функції: file_search(['C:', 'backup.log', 'ideas.txt'], 'ideas.txt')
Повертає: 'C:/ideas.txt'
Виклик функції: file_search([ 'D:', ['recycle bin'], ['tmp', ['old'], ['new folder1', 'asd.txt', 'asd.bak', 'find.me.bak' ] ], 'hey.py'], 'find.me')
Повертає: False
Виклик функції: file_search([ '/home', ['user1'], ['user2', ['my pictures'], ['desktop', 'not this', 'and not this', ['new folder', 'hereiam.py' ] ] ], 'work.ovpn', 'prometheus.7z', ['user3', ['temp'], ], 'hey.py'], 'hereiam.py')
Повертає: '/home/user2/desktop/new folder/hereiam.py'

Лапки не повертаються і використані тут для розрізнення логічного False та рядків.

function file_search(folder, filename){
      var find = false;
      var list = [];

      function f(folder, filename){
         var i = 0; 
         while(i < folder.length && !find) {
             if( i == 0){
                 list.push(folder[i]);
             }
             if(folder[i] === filename){
                 list.push(folder[i]);
                 find = true;
             }
             if( typeof(folder[i]) == 'object') {
                 f(folder[i], filename);
             }
             
             if( i == folder.length-1 && find == false ){
                 list.pop();
             }
             
             i++;
         }

         if(find) {
             return list.join('/');
         } else { return find ; }
    }
    return f(folder, filename);
  }


      console.log(file_search(['C:'], 'crack.exe'));
     /* False */
      console.log(file_search(['C:', '1.txt', '2.txt', '3.txt', '4.txt'], '4.txt'));
     /* C:/4.txt */
      console.log(file_search(['C:', '1.txt', '2.txt', '3.txt', '4.txt'], '1.txt'));
     /* C:/1.txt */
     console.log(file_search(['D:', ['recycle bin'], ['tmp', ['old'], ['new folder1', 'asd.txt', 'asd.bak', 'find.me']], 'hey.py'], 'find.me'));
     /* D:/tmp/new folder1/find.me */
     console.log(file_search(['/tmp', ['1', ['2', ['3', ['4', ['5', 'key1', 'key2', 'key3']]]]]], 'key3'));
     /* /tmp/1/2/3/4/5/key3 * /

2 Востаннє редагувалося koala (04.05.2018 17:40:37)

Re: Чи можливий такий варіант розв`язку задачі.

Рекурсія загалом не дуже вітається, але навряд чи вам передадуть список на 10000 вкладених масивів, так що годиться.
Звертаю увагу, що параметр filename у рекурсивній функції не змінюється, відповідно, його можна нікуди не передавати, це допоможе рекурсії (насправді, як я розумію, ні, але принаймні виглядатиме простіше).
А от те, що функція f не завжди повертає результат, а замість того активно працює зі стеком - це погано. Власне, рекурсія і має використовуватися, щоб приховувати всі ці push/pop викликами рекурсії, інакше у неї немає переваг перед циклом.
Що ж до того, чи це "можливо" - воно ж працює, значить, можливо.

якось так
function file_search(folder, filename){
    function f(folder){
        for (var entry in folder) {
            if( typeof(folder[entry])==='object') {
                result = f(folder[entry]);
                if(result !== false) 
                    return folder[0]+'\\'+result;
            } else {
                if( folder[entry] === filename )
                    return folder[0]+'\\'+filename; 
            }
        }
        return false;
    }
    return f(folder);
 }
Подякували: Tar1