0

I have 3 arguments in a move function those are list,source and destination. List is here :

const list = [
      {
        id: '1',
        name: 'Folder 1',
        files: [
          { id: '2', name: 'File 1' },
          { id: '3', name: 'File 2' },
          { id: '4', name: 'File 3' },
          { id: '5', name: 'File 4' },
        ],
      },
      {
        id: '6',
        name: 'Folder 2',
        files: [{ id: '7', name: 'File 5' }],
      },
    ];

in a given function I should enter the source and destination and I could move for example move(list, '4', '6') then I expect file with id 4 moved to the folder which has id 6.

Like that :

const result = [
  {
    id: '1',
    name: 'Folder 1',
    files: [
      { id: '2', name: 'File 1' },
      { id: '3', name: 'File 2' },
      { id: '5', name: 'File 4' },
    ],
  },
  {
    id: '6',
    name: 'Folder 2',
    files: [
      { id: '7', name: 'File 5' },
      { id: '4', name: 'File 3' },
    ],
  },
];

I moved it Received: {"files": [{"id": "7", "name": "File 5"}, {"id": "4", "name": "File 3"}], "id": "6", "name": "Folder 2"} but I couldn't delete the value that id is 4.

Here is my code

let copyList =list.slice();

 const filteredVal =  copyList[0].files.find((file: { id: Object; })=> { 

  return file.id == source
 } );// 2-3-4-5

//  if (copyList[0].files.id === source){
//   delete copyList[0].files.source
//  } -> Doesn't work.


 copyList[1].files.push(filteredVal);

 return copyList[1]

I am using typescript also I'm testing it with jest I don't wait for the direct answers just I need steps to go or any need to write from scratch with another technique.

1
  • should be able to move 1 to 7 also ? EX -Move(List, 1,7) Commented Nov 17, 2022 at 14:10

3 Answers 3

2

This should work, I leave you some comments

function move(list, fileId, folderId) {
  // This does not copy the objects inside list, prefer something like JSON.parse(JSON.stringify(list)) to do a deep copy
  const copyList = list.slice();
  // Get the files from the folder where is located your fileId
  const { files: originFiles } = copyList.find(({ files }) => files.some(({ id }) => id === fileId))
  // Get the index of the file to move
  const fileToMoveIndex = originFiles.findIndex(({ id }) => id === fileId)
  // Find the destination folder with the folderId
  const destinationFolder = copyList.find(({ id }) => id === folderId)
  // Add the file in the destination folder
  destinationFolder.files.push(originFiles[fileToMoveIndex])
  // Remove the file from it origin folder
  originFiles.splice(fileToMoveIndex, 1)
  return destinationFolder
}
move(list, '4', '6');
console.log(list);
<script>
const list = [
  {
    id: '1',
    name: 'Folder 1',
    files: [
      { id: '2', name: 'File 1' },
      { id: '3', name: 'File 2' },
      { id: '4', name: 'File 3' },
      { id: '5', name: 'File 4' },
    ],
  },
  {
    id: '6',
    name: 'Folder 2',
    files: [{ id: '7', name: 'File 5' }],
  },
];
</script>

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

4 Comments

Because the originalList is modified ? I left him a comment to explain it.
I changed your console.log to show it does work, but you still modify the original. OP seems to want to copy
And if you are talking about the return, he wanted to return the folder were the file is transfered, let you check and verify your own code
I do not see OP wanted to return the folder... The code he posted seems that he wants to return the copy of the list with the modifications
0

Here is the long way around without testing if the id was found

NOTE how I copy the array - slice will not make a deep copy.

const move = (list, from, to) => {
  const arr = JSON.parse(JSON.stringify(list)); // safer than slice
  const fromFiles = arr.find(({files}) => files.some(({id}) =>  id === from))?.files; // array of source files
  if (!fromFiles || fromFiles.length === 0) return null;
  const fromFile = fromFiles.splice(fromFiles.findIndex(({id}) =>  id === from),1);  // remove and return source file
  const toFiles = arr.find(({id}) => id === to)?.files;
  if (!toFiles || toFiles.length === 0) return null;
  toFiles.push(fromFile); // push the file to the destination array.
  return arr
  
}
console.log("--- 1 ---\n"); 
console.log(move(list, '4', '6')); // new array
console.log("--- Original --- \n"); 
console.log(list); // old unaffected array
console.log("--- 2 ---\n"); 
console.log(move(list, '8', '6')); // from not found
console.log("--- Original --- \n"); 
console.log(list); // old unaffected array
console.log("--- 3 ---\n"); 
console.log(move(list, '7', '6')); // to not found
console.log("--- Original --- \n"); 
console.log(list); // old unaffected array
<script>
const list = [
  {
    id: '1',
    name: 'Folder 1',
    files: [
      { id: '2', name: 'File 1' },
      { id: '3', name: 'File 2' },
      { id: '4', name: 'File 3' },
      { id: '5', name: 'File 4' },
    ],
  },
  {
    id: '6',
    name: 'Folder 2',
    files: [{ id: '7', name: 'File 5' }],
  },
];
</script>

2 Comments

@3limin4t0r Why would files.some fit better? Here it will work the same as some
I did not realise which "find" you meant. I have changed to some
0

If you don't mind a mutating solution, here is one that is fairly easy to understand.

Loop through all files in every folder until you find the file that matches the provided sourceFileID. Then search the folder that matches the provided destinationFolderID. If both are found, remove the file from the source and add it to the destination.

function move(folders, sourceFileID, destinationFolderID) {
  // intentional `var` usage, these variables are accessible outside of the for-block
  for (var sourceFolder of folders) {
    var iFile = sourceFolder.files.findIndex(file => file.id == sourceFileID);
    if (iFile >= 0) break;
  }
  
  if (!(iFile >= 0)) return; // source file not found
  
  const destinationFolder = folders.find(folder => folder.id == destinationFolderID);
  
  if (!destinationFolder) return; // destination folder not found
  
  const [file] = sourceFolder.files.splice(iFile, 1);
  destinationFolder.files.push(file);
}

const list = [
  {
    id: '1',
    name: 'Folder 1',
    files: [
      { id: '2', name: 'File 1' },
      { id: '3', name: 'File 2' },
      { id: '4', name: 'File 3' },
      { id: '5', name: 'File 4' },
    ],
  },
  {
    id: '6',
    name: 'Folder 2',
    files: [{ id: '7', name: 'File 5' }],
  },
];

move(list, "4", "6");
console.log(list);
div.as-console-wrapper { max-height: 100% }

2 Comments

Why the loop. That is so inelegant
@mplungjan The loop is there to both find the sourceFolder and the index of the relevant file. It might not be the most elegant, but it is more efficient than your solution. You have to use files.find() once to find the folder, then use files.findIndex() to find the index in the folder. Thus iterating files twice. This solution does both steps at once.

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.