이 문제범위 사이에서 난수를 생성하는 것에 관한 것입니다. 이는 괜찮지만 제 경우에는 적합하지 않습니다.
제 생각에는 SQL 용어로 설명하겠습니다. 왜냐하면 제 생각에는 코드 결과로 SQL 스크립트를 작성하는 것 bash
입니다 .bash
두 개의 MySQL 테이블이 있습니다. 하나는 사람이고 다른 하나는 장소입니다. 각 레코드에는 1~139(장소) 및 1~1519(사람) 범위의 고유한 정수 ID가 있습니다. 이는 외래 키를 통해 서로 관련되어 있습니다. 즉, 한 곳에는 많은 사람이 있을 수 있지만 한 사람에게는 한 곳만 있을 수 있습니다.
# 1-139 # 1-1519
place1 → person1
→ person2
→ person3
... and so on
지금 내가 가지고 있는 데이터는 한곳에 있어요모두사람들은 다른 장소와는 다른 방식으로 연결되어 있습니다.
장소가 139개이고 사람이 1519명이니까 1개 장소가 있고 사람이 1519명이에요.
내 목표는 무작위로 사람들을 장소에 배정하고 각 장소에 최소한 한 명씩 배치하는 것입니다.
지금까지 내 코드는 다음과 같습니다.
$ c=1519
$ while [[ $c -ne 0 ]]; do
x=$((shuf -i 1-139 -n 1))
[[ $x -gt 139 ]] && continue
echo $x
(( c-- ))
done
이 코드는 1~139 사이의 1519개의 난수를 생성하므로 이제 각 사람을 임의의 위치에 연결할 수 있습니다.
내 질문은 다음과 같습니다
- 이를 달성하는 더 효율적인 방법이 있습니까?
- 모든 장소에 최소한 한 사람이 있는지 어떻게 제어할 수 있나요?
나는 에서 이 작업을 수행하는 것을 선호 bash
하지만 이를 포함하지 않는 다른 솔루션에도 열려 있습니다.
답변1
일반적인 도구(적어도 Linux 배포판에서는)를 사용하여 이 작업을 수행하려는 경우 가장 효율적인 방법은 아마도 다음과 같이 질문하는 것입니다 shuf
.
shuf -i 1-139 -n 1519 -r
그러면 1에서 139 사이에서 무작위로 선택된 1519개의 숫자가 생성됩니다.
모든 장소에 사람이 있는지 확인하려면 먼저 139개의 숫자를 반복하지 않고 섞으세요.
shuf -i 1-139
shuf -i 1-139 -n 1380 -r
"첫 번째 139" 효과를 줄이려면(처음 139명이 모두 다른 위치에 있게 됨) 덱을 다시 섞습니다.
(shuf -i 1-139; shuf -i 1-139 -n 1380 -r) | shuf
답변2
테이블에 people 이 저장되어 person
있고 각 사람이 place_id
1에서 139 사이의 정수를 가지고 있다고 가정합니다. SQL을 사용하여 person
테이블을 직접 업데이트합니다.
UPDATE person SET place_id = FLOOR(RAND()*139 + 1);
이렇게 하면 테이블의 모든 항목이 업데이트되어 place_id
키가 무작위로 지정됩니다. 하지만 완전히 테스트되지 않았습니다.
업데이트 후 다음을 사용하여 각 위치가 표시되는지 테스트할 수 있습니다.
SELECT COUNT(DISTINCT place_id) = 139 FROM person;
1
모든 위치가 표시되면 이 값이 반환되고, 그렇지 않으면 반환되어야 합니다 0
.
답변3
우리가 이 값을 원하면최대한 고르게 펴서(1519가 139의 10배의 덜 정확한 배수라는 점을 고려하면) 단지 공백을 피하는 대신 충분히 큰 반복 시퀀스 1, ..., 139, 1, ..., 139, 1, ... 및 그런 다음 처음 1519개 멤버를 섞습니다.
while seq 139; do :; done | head -n 1519 | shuf
사람을 위치에 매핑해야 하는 경우 간단히 출력 행에 번호를 매길 수 있습니다.
while seq 139; do :; done | head -n 1519 | shuf | nl
이는 모두 표준 쉘이므로 Bash 확장이 필요하지 않습니다.