Yêu cầu thg 11 9, 2020 1:12 SA 270 0 1
  • 270 0 1
+2

Xử lý dữ liệu javascript

Chia sẻ
  • 270 0 1
arr1.push({phong: "phong1", "dsnv": "1,2,3,4,5", "sl": "10"});
arr1.push({phong: "phong2", "dsnv": "1,4,5", "sl": "5"});
arr1.push({phong: "phong3", "dsnv": "1,2,3", "sl": "15"});
arr1.push({phong: "phong4", "dsnv": "1,6,5", "sl": "20"});

Chào anh chị em, số là e có dữ liệu thô như bên dưới, em cần tìm những số trong dsnv trùng nhau giữa các phòng, nếu phòng cùng có mã nhân viên thì phòng có số lượng lớn hơn giảm đi 1, vậy có cách nào ngắn gọn hơn không ạ, theo cách em làm thì rất dài và nhiều vòng lặp nên thấy hơi tù ạ. mong anh chị em giúp đỡ

Avatar Trần Xuân Thắng @tranxuanthang
thg 11 9, 2020 1:54 SA

Bạn có thể viết nhanh một ví dụ đầu ra mong muốn được không. Và cái phần "dsnv": "1,2,3,4,5" tại sao không lưu cái 1,2,3,4,5 ở dạng mảng nhỉ.

Avatar Z @zingler
thg 11 9, 2020 1:57 SA

à mình lưu dữ liệu trong sql dạng string, muốn dạng mảng cũng được mà bác. Ví dụ ở trên thì 4 phòng đều có nv 1, mà phòng 2 số lượng ít nhất nên các phòng khác số lượng -1 hết.

Avatar Tran Duc Thang @thangtd90
thg 11 9, 2020 2:38 SA

@zingler

Yêu cầu của bạn vẫn còn nhiều điểm mập mờ quá nhỉ, bạn miêu tả chi tiết hơn được không 😄

Ví dụ như trường hợp mình có dữ liệu thế này, thì bạn kỳ vọng output sẽ trả ra như thế nào nhỉ 🤔

arr1.push({phong: "phong1", "dsnv": "1,2,3,4,5", "sl": "6"});
arr1.push({phong: "phong2", "dsnv": "1,2,4,", "sl": "6"});
arr1.push({phong: "phong3", "dsnv": "1,2,3", "sl": "6"});
arr1.push({phong: "phong4", "dsnv": "2,3,4", "sl": "5"});
arr1.push({phong: "phong5", "dsnv": "3,4", "sl": "4"});
Avatar Z @zingler
thg 11 9, 2020 2:46 SA

@thangtd90

phòng 1: 3
phòng 2: 4
phòng 3: 4
phòng 4: 3
phòng 5: 2

Output đại khái sẽ vậy, như với mã nhân viên 1 thì phòng 1,2,3 đều có, nên khi so thì sẽ chọn cái có số lượng nhỏ nhất, nếu bằng nhau thì giữ phòng đang đi so, ở ví dụ này thì phòng 2 và 3 sẽ bị trừ.

Avatar Tran Duc Thang @thangtd90
thg 11 9, 2020 3:04 SA

@zingler Tức là nếu 2 hoặc 3 phòng có số lượng bằng nhau và cùng là số lượng nhỏ nhất, thì sẽ trừ ở tất cả các phòng bạn nhỉ 🤔

Cụ thể thì với dữ liệu ở trên thì sẽ qua các bước xử lý

Ban đầu
Phòng 1: 1,2,3,4,5 (msnv) - 6 (sl)
Phòng 2: 1,2,4 - 6
Phòng 3: 1,2,3 - 6
Phòng 4: 2,3,4 - 5
Phòng 5: 3,4 - 4

Step 1, so sánh mã nhân viên 1
Phòng 1: 1,2,3,4,5 - 6
Phòng 2: 1,2,4 - 5 // Trừ đi 1 do phòng có số lượng ít nhất 
Phòng 3: 1,2,3 - 5 // Trừ đi 1 do phòng có số lượng ít nhất 
Phòng 4: 2,3,4 - 5
Phòng 5: 3,4 - 4

Step 2, so sánh mã nhân viên 2
Phòng 1: 1,2,3,4,5 - 6
Phòng 2: 1,2,4 - 4 // Trừ đi 1 do phòng có số lượng ít nhất 
Phòng 3: 1,2,3 - 4 // Trừ đi 1 do phòng có số lượng ít nhất 
Phòng 4: 2,3,4 - 4 // Trừ đi 1 do phòng có số lượng ít nhất 
Phòng 5: 3,4 - 4

Step 3, so sánh mã nhân viên 3
Phòng 1: 1,2,3,4,5 - 6
Phòng 2: 1,2,4 - 4 
Phòng 3: 1,2,3 - 3 // Trừ đi 1 do phòng có số lượng ít nhất 
Phòng 4: 2,3,4 - 3 // Trừ đi 1 do phòng có số lượng ít nhất 
Phòng 5: 3,4 - 3 // Trừ đi 1 do phòng có số lượng ít nhất 

Step 4, so sánh mã nhân viên 4
Phòng 1: 1,2,3,4,5 - 6
Phòng 2: 1,2,4 - 4 
Phòng 3: 1,2,3 - 3
Phòng 4: 2,3,4 - 2 // Trừ đi 1 do phòng có số lượng ít nhất 
Phòng 5: 3,4 - 2 // Trừ đi 1 do phòng có số lượng ít nhất 

Step 5, so sánh mã nhân viên 5
Phòng 1: 1,2,3,4,5 - 5 // Trừ đi 1 do phòng có số lượng ít nhất 
Phòng 2: 1,2,4 - 4 
Phòng 3: 1,2,3 - 3
Phòng 4: 2,3,4 - 2
Phòng 5: 3,4 - 2

Kết quả có vẻ ra khác với kết quả của bạn ở trên 🤔

Avatar Z @zingler
thg 11 9, 2020 3:16 SA

@thangtd90 ở step 2 số lượng phòng 2 đã nhỏ hơn phòng 1 rồi bác, đề bài là tìm ra nhân viên ở cùng nằm 2 phòng, thì ưu tiên phòng số lượng nhỏ nhất, tránh số liệu ảo, ví dụ tuy ông này được phân công làm ở 2 phòng, nhưng thời điểm hiện tại ông ấy ngồi ở 1 phòng thôi, phòng còn lại có ghế trống thì dựa vào code để hiển thị số lượng dư ghế cho người khác ấy bác

Avatar Tran Duc Thang @thangtd90
thg 11 9, 2020 3:21 SA

@zingler

ở step 2 số lượng phòng 1 đã nhỏ hơn phòng 2 rồi bác

Step 2 là step so sánh đến nhân viên có mã số là 2 bạn nhỉ. Lúc đó thì làm sao phòng 1 lại có số lượng nhỏ hơn phòng 2 được nhỉ 🤔

Cả 3 phòng 1, 2, 3 đều khởi đầu với số lượng là 6. Và như ở phía trên thì bạn có ghi là

như với mã nhân viên 1 thì phòng 1,2,3 đều có, nên khi so thì sẽ chọn cái có số lượng nhỏ nhất, nếu bằng nhau thì giữ phòng đang đi so, ở ví dụ này thì phòng 2 và 3 sẽ bị trừ.

thì tức là sau Step 1, thì phòng 2 và 3 sẽ còn lại 5, và phòng 1 sẽ là 6, chứ nhỉ 🤔

Avatar Z @zingler
thg 11 9, 2020 3:37 SA

@thangtd90

Ban đầu
Phòng 1: 1,2,3,4,5 (msnv) - 6 (sl)
Phòng 2: 1,2,4 - 6
Phòng 3: 1,2,3 - 6
Phòng 4: 2,3,4 - 5
Phòng 5: 3,4 - 4

Step 1, so sánh mã nhân viên 1
Phòng 1: 1,2,3,4,5 - 6 <
Phòng 2: 1,2,4 - 5 // Trừ đi 1 so phòng có số lượng ít nhất 
Phòng 3: 1,2,3 - 5 // Trừ đi 1 so phòng có số lượng ít nhất 
Phòng 4: 2,3,4 - 5
Phòng 5: 3,4 - 4

Step 2, so sánh mã nhân viên 2
Phòng 1: 2,3,4,5 - 5 // Trừ đi 1 so phòng có số lượng ít nhất 
Phòng 2: 2,4 - 5 <
Phòng 3: 2,3 - 4 // Trừ đi 1 so phòng có số lượng ít nhất 
Phòng 4: 2,3,4 - 4 // Trừ đi 1 so phòng có số lượng ít nhất 
Phòng 5: 3,4 - 4

Step 3, so sánh mã nhân viên 3
Phòng 1: 3,4,5 - 4 // Trừ đi 1 so phòng có số lượng ít nhất 
Phòng 2: 4 - 5 
Phòng 3: 3 - 4 <
Phòng 4: 3,4 - 3 // Trừ đi 1 so phòng có số lượng ít nhất 
Phòng 5: 3,4 - 3 // Trừ đi 1 so phòng có số lượng ít nhất 

Step 4, so sánh mã nhân viên 4
Phòng 1: 4,5 - 3 // Trừ đi 1 so phòng có số lượng ít nhất 
Phòng 2: 4 - 4  // Trừ đi 1 so phòng có số lượng ít nhất 
Phòng 3:  - 4  
Phòng 4: 4 - 3 <
Phòng 5: 4 - 2 // Trừ đi 1 so phòng có số lượng ít nhất 

Step 5, so sánh mã nhân viên 5
Phòng 1: 5 - 3
Phòng 2:  - 4 
Phòng 3:  - 4  
Phòng 4:  - 3 
Phòng 5:  - 2 

Đề bài là vậy bác ạ

Avatar Tran Duc Thang @thangtd90
thg 11 9, 2020 3:46 SA

@zingler à mình hiểu rồi, cám ơn bạn nhé 😄 Ở trên mình hiểu nhầm một chút, phải là giữ nguyên số lượng ở phòng có số lượng ít nhất, và trừ 1 ở tất cả các phòng còn lại, chứ không phải là trừ 1 ở các phòng có số lượng ít nhất 😄

1 CÂU TRẢ LỜI


Đã trả lời thg 11 9, 2020 7:56 SA
Đã được chấp nhận
0

Bạn thử xem xử lý như dưới đây có được không 😄

Cũng phải mất 2 vòng lặp lồng nhau (^^;)

// Khởi tạo dữ liệu để test
let rooms = [];
rooms.push({id: "phong1", "staffs": "1,2,3,4,5", "capacity": "6"});
rooms.push({id: "phong2", "staffs": "1,2,4", "capacity": "6"});
rooms.push({id: "phong3", "staffs": "1,2,3", "capacity": "6"});
rooms.push({id: "phong4", "staffs": "2,3,4", "capacity": "5"});
rooms.push({id: "phong5", "staffs": "3,4", "capacity": "4"});

// Xử lý qua mảng các phòng họp. 
// Chuyển list nhân viên từ string sang array, và thêm vào trường để lưu số lượng thực tế
let staffs = [];
for (let room of rooms) {
  room.staffsArray = room.staffs.split(',');
  // Tạo biến staffs để lưu danh sách mã số nhân viên, không bị trùng lặp
  staffs = staffs.concat(room.staffsArray.filter((item) => item && staffs.indexOf(item) < 0)); 
  room.realCapacity = parseInt(room.capacity);
}

// Lặp qua từng nhân viên một
// Với mỗi nhân viên thì lặp qua từng phòng, phòng nào có nhân viên đó thì trừ đi một
// Đồng thời lưu lại thông tin xem phòng nào có số lượng ít nhất
// Sau đó, tăng lại một cho phòng có số lượng ít nhất này
for (let staff of staffs) {
  let minRoomIndex;
  let minNum;
  for (index in rooms) {
    let room = rooms[index]; 
    if (room.staffsArray.includes(staff)) {
      if (minRoomIndex === undefined || room.realCapacity < minNum) {
        minNum = room.realCapacity;
        minRoomIndex = index;
      }
      room.realCapacity--;
    }
  }
  rooms[minRoomIndex].realCapacity += 1;
}

Mình tính ra thì với dữ liệu ở trên sẽ ra kết quả

phòng 1: 3
phòng 2: 4
phòng 3: 4
phòng 4: 3
phòng 5: 2

Có vẻ trùng với kết quả mong muốn của bạn ở phần comment rồi 😄 Không rõ có đúng là đề bài yêu cầu thế không nhỉ 🤔

Chia sẻ
Avatar Z @zingler
thg 11 9, 2020 8:33 SA

Vậy mình trừ hết rồi dựa theo số lượng mà + thì hay hơn bạn nhỉ? nếu làm theo này sẽ có trường hợp như sau

Bảng gốc
Phòng 1 - 1,2 - 2
Phòng 2 - 1,2,3 - 3
Phòng 3 - 2,3 - 2
Step 1
Phòng 1 - 1,2 - 2 <
Phòng 2 - 2,3 - 2 \\ Bị trừ
Phòng 3 - 2,3 - 2
Step 2
Phòng 1 -  1,2 - 2 <
Phòng 2 - 3 - 1 \\ Bị trừ
Phòng 3 - 3 - 1 \\ Bị trừ
Step 3
Phòng 1 - 1,2 - 2
Phòng 2 - 3 - 1 <
Phòng 3 - null - 0 \\ Bị trừ

nhưng thực tế để phân bố đều tránh phòng bị ùn tắc thì sẽ có dạng

Phòng 1: 1
Phòng 2: 1
Phòng 3: 1

hoặc do mình xử lý từ sql đã sai rồi :-<

Avatar Tran Duc Thang @thangtd90
thg 11 9, 2020 8:46 SA

@zingler Căn bản là mục đích cuối cùng bạn muốn làm gì, và đang cố gắng giải quyết vấn đề như thế nào thôi 😄

Nếu mục đích là để phân bố nhân viên vào trong từng phòng, thì có vẻ ngay logic ban đầu bạn đưa ra ở câu hỏi đã có vẻ không ổn rồi 🤔

Cho mình hỏi rõ hơn, cái trường số lượng "sl" ở đây là số lượng gì vậy bạn nhỉ? Số lượng nhân viên (đếm từ trong mảng danh sách mã số nhân viên), hay sức chứa còn lại của phòng 🤔

Avatar Z @zingler
thg 11 9, 2020 8:49 SA

@thangtd90 à đúng rồi, từ đầu cái đề đã sai rồi, thật ra nó là số lượng nhân viên = length của dsnv rồi , thế k nghĩ ra lưu dsnv như bạn nhỉ, dựa theo cách của bạn mình thấy ổn rồi

Avatar Tran Duc Thang @thangtd90
thg 11 9, 2020 9:03 SA

@zingler Uhm, nếu là số lượng nhân viên thì có thể đếm trực tiếp từ cái mảng nhân viên ra rồi, nên không cần phải lưu nó lại làm gì. Lúc đó đoạn code khai báo ban đầu có thể sửa lại một cách gọn hơn là

let rooms = [];
rooms.push({id: "phong1", "staffs": "1,2,3,4,5"});
rooms.push({id: "phong2", "staffs": "1,2,4"});
rooms.push({id: "phong3", "staffs": "1,2,3"});
rooms.push({id: "phong4", "staffs": "2,3,4"});
rooms.push({id: "phong5", "staffs": "3,4"});

let staffs = [];
for (let room of rooms) {
  room.staffsArray = room.staffs.split(',');
  // Tính trực tiếp số lượng từ độ dài của mảng
  room.staffCounts = room.staffsArray.length; 
  staffs = staffs.concat(room.staffsArray.filter((item) => item && staffs.indexOf(item) < 0));
}

thôi 😄

Tuy nhiên đoạn code kia sau khi chạy thì sẽ ra kết quả

Phòng 1: 1 (chứa người có mã nhân viên là 5)
Phòng 2: 1 (1)
Phòng 3: 2 (2, 3)
Phòng 4: 1 (4)
Phòng 5: 0

Trong khi nếu sắp xếp chuẩn thì mỗi phòng có thể chứa 1 người là

Phòng 1: 1 (5)
Phòng 2: 1 (1)
Phòng 3: 1 (2)
Phòng 4: 1 (3)
Phòng 5: 1 (4)

Tức miêu tả về thuật toán bạn đưa ra ở đề bài, đó là giữ lại mã số nhân viên ở phòng có số lượng nhỏ nhất, và trừ số lượng ở các phòng khác đi 1, thì chưa phải là thuật toán tối ưu nhất rồi (^^;)

Avatar Z @zingler
thg 11 9, 2020 9:09 SA

@thangtd90 bởi vậy mình mới lên tham khảo anh chị em đó haha, với cách làm của bạn hiện tại mình thấy ok r, cảm ơn bạn nhiều nha

Avatar Z @zingler
thg 11 9, 2020 9:23 SA

@thangtd90 với bài toán này bạn có nghĩ ra được hướng giải nào tối ưu nhất cho bài toán không ạ? từ khâu sql luôn ấy ạ

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí