-3

enter code hereHow do i randomly select more than one item from a list in linux scripting ?

For example:-

Column A Column B

Itemcode    Quantity
COM#004     2
COM#005     3
COME001     10
COMT000     3
COMT001     3
COMH000     1
COMH000     1
COM#006     2
CT100H000   1

Inputs:- the number of item to select

for example :- the number of item to select = 6

COME001
COMT000
COM#004
COM#006
COMT001
COMH000

after an set of items been selected, quatity has to be reduced. should be able to pick item for next select till its quantity gets zero.

It works but I wanted the stock to be maintained for example. on the output 1:- COME001 is picked and stock shows as 9 but on output 2 it has not been picked that's ok its picks randomly but stock should be maintained as 9 instead of 10

Output 1:- $ python test.py Picked: ['COM#004', 'COM#005', 'COMH000', 'COM#004', 'CT100H000', 'COME001']

Stock left COMH000 1 COMT000 3 COMT001 3 CT100H000 0 COM#005 2 COM#004 0 COM#006 2 COME001 9

Output 2:- $ python test.py Picked: ['COMH000', 'COMT000', 'COM#004', 'COM#006', 'COM#005', 'COMH000']

Stock left COMH000 0 COMT000 2 COMT001 3 CT100H000 1 COM#005 2 COM#004 1 COM#006 1 COME001 10

  • 2
    If an item currently has a quantity > 1 can it be selected multiple times in one set? – PM 2Ring Jul 19 '15 at 07:20
  • 1
    BTW, this isn't a good question for SO. This isn't a site for programming challenges, it's a Q&A site to help you fix programs that aren't working correctly. Maybe you should take a look at [Programming Puzzles & Code Golf](http://codegolf.stackexchange.com). – PM 2Ring Jul 19 '15 at 07:27
  • yes, If an item currently has a quantity > 1 can it be selected multiple times – user3742796 Jul 19 '15 at 07:28
  • for example:- I have full list of items with available quantity. I need to generate random list [mutilple list] of more than one item picked from the given list. I need an option to select number of items per random list and till the quantity is greater than zero item has to be picked from the given list. – user3742796 Jul 19 '15 at 07:29
  • So it's ok if one of these random list has several of `COME001` in it? – PM 2Ring Jul 19 '15 at 07:35
  • yes that would be fine – user3742796 Jul 19 '15 at 07:38
  • I want multiple random list with some may have 3 iterms, some may have 4 items, and upto 7 – user3742796 Jul 19 '15 at 07:39
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/83655/discussion-between-user3742796-and-pm-2ring). – user3742796 Jul 19 '15 at 07:42
  • possible duplicate of [Fitness proportionate selection (roulette wheel selection) in Python](http://stackoverflow.com/questions/10324015/fitness-proportionate-selection-roulette-wheel-selection-in-python) – User Jul 19 '15 at 07:42
  • 1
    @PM2Ring: This question is completely off topic on PPCG and has been closed and deleted since the user posted it. Please don't suggest posting on sites you're not at all familiar with. – Dennis Jul 19 '15 at 14:13
  • Sorry @Dennis. I'll be more careful in future. But in my defence I only told him to _look_ at PPCG, I didn't actually suggest that he post this question there. Although I'm not a member of PPCG I understand that this question would be quite unsuitable for PPCG in its current form. – PM 2Ring Jul 19 '15 at 14:25

2 Answers2

0

If speed is not important, the following approach could be used in Python. The data must be stored in a CSV file and updated each time. I am assuming a simple tab delimited file as shown in the question:

import random, collections, csv

def pick_non_zero(count):
    ditems = collections.defaultdict(int)

    # Read the current stock file in
    with open("stock.csv", "r") as f_input:
        csv_input = csv.reader(f_input, delimiter="\t")
        headers = csv_input.next()

        for item, quantity in csv_input:
            ditems[item] += int(quantity)

    lchoices = []

    for n in range(count):
        # Create a list of items with quantity remaining
        lnon_zero = [item for item, quantity in ditems.items() if quantity > 0]

        if len(lnon_zero) == 0:
            lchoices.append("No more stock")
            break

        # Pick one
        choice = random.choice(lnon_zero)
        # Reduce quantity by 1
        ditems[choice] -= 1
        lchoices.append(choice)

    # Write the updated stock back to the file
    with open("stock.csv", "wb") as f_output:
        csv_output = csv.writer(f_output, delimiter="\t")
        csv_output.writerow(headers)

        for item, quantity in ditems.items():
            csv_output.writerow([item, quantity])

    print "Stock left"

    for item, quantity in ditems.items():
        print "%-10s  %d" % (item, quantity)

    return lchoices

lpicked = pick_non_zero(6)

print
print "Picked:", lpicked

Giving the following possible output:

Stock left
COMH000     0
COMT000     2
COMT001     3
CT100H000   0
COM#005     3
COM#004     2
COM#006     2
COME001     8

Picked: ['CT100H000', 'COMH000', 'COME001', 'COME001', 'COMH000', 'COMT000']

Updated to use a CSV file. Tested using Python 2.7.

Martin Evans
  • 45,791
  • 17
  • 81
  • 97
  • It does _seem_ inefficient creating `lnon_zero` each time in the loop, but it's actually not too bad, especially if the size of `items` isn't too big. However, the OP wants the code to spit out lists of various length, with each list containing multiple choices; the same item is allowed to occur multiple times in a given list. – PM 2Ring Jul 19 '15 at 08:16
  • File "test.in", line 28 ditems = {item: quantity for item, quantity in items} ^ SyntaxError: invalid syntax – user3742796 Jul 19 '15 at 09:43
  • [root@xcatmn ~]# python --version Python 2.6.6 [root@xcatmn ~]# – user3742796 Jul 19 '15 at 09:47
  • It uses a dictionary compression which I think was added in Python 2.7. A list compression could also be used or even a loop. – Martin Evans Jul 19 '15 at 09:50
  • See [this post](http://stackoverflow.com/questions/1747817/python-create-a-dictionary-with-list-comprehension) for an example on how to change it. – Martin Evans Jul 19 '15 at 10:01
  • on 1st output COME001 has been picked and 1 qty got reduced from stock but 2nd output COME001 not picked and again its show qty as 10 whereas i expect 9 Output 1:- Picked: ['COMT000', 'COMH000', 'COMT001', 'COM#005', 'COME001', 'CT100H000'] Stock left: {'COMH000': 0, 'COMT000': 2, 'COMT001': 2, 'CT100H000': 0, 'COM#005': 2, 'COM#004': 2, 'COM#006': 2, 'COME001': 9} Output 2:- Picked: ['CT100H000', 'COM#005', 'COM#005', 'COM#004', 'COMH000', 'COM#006'] Stock left: {'COMH000': 0, 'COMT000': 3, 'COMT001': 3, 'CT100H000': 0, 'COM#005': 1, 'COM#004': 1, 'COM#006': 1, 'COME001': 10} – user3742796 Jul 20 '15 at 07:04
  • Try now, I'd not spotted you had multiple items with the same name. They are now added together. If you need them left seperate the dictionary solution would need to be changed to a slower list lookup. – Martin Evans Jul 23 '15 at 07:24
  • stock need to maintained for example 1st OP:- COME001 is picked and stock shows as 9 but on output 2 it has not been picked that's OK its picks randomly but stock should be maintained as 9 instead of 10 2nd OP:- $ python test.py Picked: ['COM#004', 'COM#005', 'COMH000', 'COM#004', 'CT100H000', 'COME001'] Stock left COMH000 1 COMT000 3 COMT001 3 CT100H000 0 COM#005 2 COM#004 0 COM#006 2 COME001 9 Output 2:- $ python test.py Picked: ['COMH000', 'COMT000', 'COM#004', 'COM#006', 'COM#005', 'COMH000'] Stock left COMH000 0 COMT000 2 COMT001 3 CT100H000 1 COM#005 2 COM#004 1 COM#006 1 COME001 10 – user3742796 Jul 29 '15 at 16:46
  • For the first random pick:- 1. Pick item randomly from the main list 2. Updated stock on the main list for all the items including item picked and not picked. Please help Martin For the second random pick:- 1. Pick item randomly from the updated list 2. Updated stock on the main list for all the items including item picked and not picked. Martin, Code which you have given is what i wanted by it doesn't maintain stock. Please help – user3742796 Jul 29 '15 at 16:58
  • To maintain stock levels between invocations of the script, the data would need to be stored in a file, not statically in the script itself. The script would need to read the file in, process it and write the updated results back to the file. The script as it stands will always start with the same stock levels. The data will need to be stored in CSV format. – Martin Evans Jul 29 '15 at 17:42
  • The new script reads your stock from a CSV file. You will need to create this. I have assumed tab delimited looking the same as your question. – Martin Evans Jul 29 '15 at 18:09
0

You can use random.sample() for that,

import random

# Reading in all the lines
with open('input') as f:
    lines = f.readlines()

# Deleting first line
del lines[:1]

# Picking 6 unique list items randomly
print("\n".join(random.sample(lines, 6)))

See https://docs.python.org/2/library/random.html?highlight=random%20sample#random.sample.

Baris Demiray
  • 1,539
  • 24
  • 35