A jagged array in Python is pretty much a list of lists as you mentioned.

I would use a dictionary to store the counselors activity information, where the key is the name of the counselor, and the value is the list of activities the counselor will be in charge of e.g.

counselors_activities = {"Adam": ["archery", "canoeing"],
                      "Bob": ["frisbee", "golf", "painting", "trampoline"],
                      "Carol": ["tennis", "dance", "skating"],
                      "Denise": ["cycling"],
                      "Eddie": ["horseback", "fencing", "soccer"],
                      "Fiona": ["painting"],
                      "George": ["basketball", "football"]}

And access each counselor in the dictionary as such:

counselors_activites["Adam"] # when printed will display the result => ['archery', 'canoeing']

In regards to the question, I would store the list of activities available in a list, and anytime an activity is chosen, remove it from the list and add it to the counselor in the dictionary as such:

list_of_available_activities.remove("archery")
counselors_activities["Adam"].append("archery")

And if a counselor no longer was in charge of the activity, remove it from them and add it back to the list of available activities.

Update: I have provided a more fully fledged solution below based on your requirements from your comments.

Text file, activites.txt:

Adam: archery, canoeing
Bob: frisbee, golf, painting, trampoline
Carol: tennis, dance, skating
Denise: cycling
Eddie: horseback, fencing, soccer
Fiona: painting
George: basketball, football

Code:

#Set of activities available for counselors to choose from

set_of_activities = {"archery",
                  "canoeing",
                  "frisbee",
                  "golf",
                  "painting",
                  "trampoline",
                  "tennis",
                  "dance",
                  "skating",
                  "cycling",
                  "horseback",
                  "fencing",
                  "soccer",
                  "painting",
                  "basketball",
                  "football"}

with open('activities.txt', 'r') as f:
    for line in f:

        # Iterate over the file and pull out the counselor's names
        # and insert their activities into a list

        counselor_and_activities = line.split(':')
        counselor = counselor_and_activities[0]
        activities = counselor_and_activities[1].strip().split(', ')

    # Iterate over the list of activities chosen by the counselor and
    # see if that activity is free to choose from and if the activity
    # is free to choose, remove it from the set of available activities
    # and if it is not free remove it from the counselor's activity list

    for activity in activities:
        if activity in set_of_activities:
            set_of_activities.remove(activity)
        else:
            activities.remove(activity)

    # Insert the counselor and their chosen activities into the dictionary

    counselors_activities[counselor] = activities

# print(counselors_activities)

I have made one assumption with this new example, which is that you will already have a set of activities that can be chosen from already available:

I made the text file the same format of the counselors and their activities listed in the question, but the logic can be applied to other methods of storage.

As a side note and a correction from my second example previously, I have used a set to represent the list of activities instead of a list in this example. This set will only be used to verify that no counselor will be in charge of an activity that has already been assigned to someone else; i.e., removing an activity from the set will be faster than removing an activity from the list in worst case.

The counselors can be inserted into the dictionary from the notepad file without having to insert them into a list.

When the dictionary is printed it will yield the result:

{"Adam": ["archery", "canoeing"],
 "Bob": ["frisbee", "golf", "painting", "trampoline"],
 "Carol": ["tennis", "dance", "skating"],
 "Denise": ["cycling"],
 "Eddie": ["horseback", "fencing", "soccer"],
 "Fiona": [], # Empty activity list as the painting activity was already chosen by Bob
 "George": ["basketball", "football"]}
Answer from user8605709 on Stack Overflow

A jagged array in Python is pretty much a list of lists as you mentioned.

I would use a dictionary to store the counselors activity information, where the key is the name of the counselor, and the value is the list of activities the counselor will be in charge of e.g.

counselors_activities = {"Adam": ["archery", "canoeing"],
                      "Bob": ["frisbee", "golf", "painting", "trampoline"],
                      "Carol": ["tennis", "dance", "skating"],
                      "Denise": ["cycling"],
                      "Eddie": ["horseback", "fencing", "soccer"],
                      "Fiona": ["painting"],
                      "George": ["basketball", "football"]}

And access each counselor in the dictionary as such:

counselors_activites["Adam"] # when printed will display the result => ['archery', 'canoeing']

In regards to the question, I would store the list of activities available in a list, and anytime an activity is chosen, remove it from the list and add it to the counselor in the dictionary as such:

list_of_available_activities.remove("archery")
counselors_activities["Adam"].append("archery")

And if a counselor no longer was in charge of the activity, remove it from them and add it back to the list of available activities.

Update: I have provided a more fully fledged solution below based on your requirements from your comments.

Text file, activites.txt:

Adam: archery, canoeing
Bob: frisbee, golf, painting, trampoline
Carol: tennis, dance, skating
Denise: cycling
Eddie: horseback, fencing, soccer
Fiona: painting
George: basketball, football

Code:

#Set of activities available for counselors to choose from

set_of_activities = {"archery",
                  "canoeing",
                  "frisbee",
                  "golf",
                  "painting",
                  "trampoline",
                  "tennis",
                  "dance",
                  "skating",
                  "cycling",
                  "horseback",
                  "fencing",
                  "soccer",
                  "painting",
                  "basketball",
                  "football"}

with open('activities.txt', 'r') as f:
    for line in f:

        # Iterate over the file and pull out the counselor's names
        # and insert their activities into a list

        counselor_and_activities = line.split(':')
        counselor = counselor_and_activities[0]
        activities = counselor_and_activities[1].strip().split(', ')

    # Iterate over the list of activities chosen by the counselor and
    # see if that activity is free to choose from and if the activity
    # is free to choose, remove it from the set of available activities
    # and if it is not free remove it from the counselor's activity list

    for activity in activities:
        if activity in set_of_activities:
            set_of_activities.remove(activity)
        else:
            activities.remove(activity)

    # Insert the counselor and their chosen activities into the dictionary

    counselors_activities[counselor] = activities

# print(counselors_activities)

I have made one assumption with this new example, which is that you will already have a set of activities that can be chosen from already available:

I made the text file the same format of the counselors and their activities listed in the question, but the logic can be applied to other methods of storage.

As a side note and a correction from my second example previously, I have used a set to represent the list of activities instead of a list in this example. This set will only be used to verify that no counselor will be in charge of an activity that has already been assigned to someone else; i.e., removing an activity from the set will be faster than removing an activity from the list in worst case.

The counselors can be inserted into the dictionary from the notepad file without having to insert them into a list.

When the dictionary is printed it will yield the result:

{"Adam": ["archery", "canoeing"],
 "Bob": ["frisbee", "golf", "painting", "trampoline"],
 "Carol": ["tennis", "dance", "skating"],
 "Denise": ["cycling"],
 "Eddie": ["horseback", "fencing", "soccer"],
 "Fiona": [], # Empty activity list as the painting activity was already chosen by Bob
 "George": ["basketball", "football"]}
Answer from user8605709 on Stack Overflow
Top answer
1 of 1
4

A jagged array in Python is pretty much a list of lists as you mentioned.

I would use a dictionary to store the counselors activity information, where the key is the name of the counselor, and the value is the list of activities the counselor will be in charge of e.g.

counselors_activities = {"Adam": ["archery", "canoeing"],
                      "Bob": ["frisbee", "golf", "painting", "trampoline"],
                      "Carol": ["tennis", "dance", "skating"],
                      "Denise": ["cycling"],
                      "Eddie": ["horseback", "fencing", "soccer"],
                      "Fiona": ["painting"],
                      "George": ["basketball", "football"]}

And access each counselor in the dictionary as such:

counselors_activites["Adam"] # when printed will display the result => ['archery', 'canoeing']

In regards to the question, I would store the list of activities available in a list, and anytime an activity is chosen, remove it from the list and add it to the counselor in the dictionary as such:

list_of_available_activities.remove("archery")
counselors_activities["Adam"].append("archery")

And if a counselor no longer was in charge of the activity, remove it from them and add it back to the list of available activities.

Update: I have provided a more fully fledged solution below based on your requirements from your comments.

Text file, activites.txt:

Adam: archery, canoeing
Bob: frisbee, golf, painting, trampoline
Carol: tennis, dance, skating
Denise: cycling
Eddie: horseback, fencing, soccer
Fiona: painting
George: basketball, football

Code:

#Set of activities available for counselors to choose from

set_of_activities = {"archery",
                  "canoeing",
                  "frisbee",
                  "golf",
                  "painting",
                  "trampoline",
                  "tennis",
                  "dance",
                  "skating",
                  "cycling",
                  "horseback",
                  "fencing",
                  "soccer",
                  "painting",
                  "basketball",
                  "football"}

with open('activities.txt', 'r') as f:
    for line in f:

        # Iterate over the file and pull out the counselor's names
        # and insert their activities into a list

        counselor_and_activities = line.split(':')
        counselor = counselor_and_activities[0]
        activities = counselor_and_activities[1].strip().split(', ')

    # Iterate over the list of activities chosen by the counselor and
    # see if that activity is free to choose from and if the activity
    # is free to choose, remove it from the set of available activities
    # and if it is not free remove it from the counselor's activity list

    for activity in activities:
        if activity in set_of_activities:
            set_of_activities.remove(activity)
        else:
            activities.remove(activity)

    # Insert the counselor and their chosen activities into the dictionary

    counselors_activities[counselor] = activities

# print(counselors_activities)

I have made one assumption with this new example, which is that you will already have a set of activities that can be chosen from already available:

I made the text file the same format of the counselors and their activities listed in the question, but the logic can be applied to other methods of storage.

As a side note and a correction from my second example previously, I have used a set to represent the list of activities instead of a list in this example. This set will only be used to verify that no counselor will be in charge of an activity that has already been assigned to someone else; i.e., removing an activity from the set will be faster than removing an activity from the list in worst case.

The counselors can be inserted into the dictionary from the notepad file without having to insert them into a list.

When the dictionary is printed it will yield the result:

{"Adam": ["archery", "canoeing"],
 "Bob": ["frisbee", "golf", "painting", "trampoline"],
 "Carol": ["tennis", "dance", "skating"],
 "Denise": ["cycling"],
 "Eddie": ["horseback", "fencing", "soccer"],
 "Fiona": [], # Empty activity list as the painting activity was already chosen by Bob
 "George": ["basketball", "football"]}
🌐
Wikipedia
en.wikipedia.org › wiki › Jagged_array
Jagged array - Wikipedia
March 5, 2026 - Jagged array can be implemented with Iliffe vector data structure in languages such as Java, PHP, Python (multidimensional lists), Ruby, C#.NET, Visual Basic.NET, Perl, JavaScript, Objective-C, Swift, and Atlas Autocode.
Discussions

python jagged array operation efficiency - Stack Overflow
I am new to Python and I am looking for the most efficient way to do operations with a jagged array. More on stackoverflow.com
🌐 stackoverflow.com
July 26, 2016
How to make a jagged array neat in Python? - Stack Overflow
0 How to apply a function on jagged Numpy arrays (unequal row lengths) without using np.apply_along_axis()? More on stackoverflow.com
🌐 stackoverflow.com
Iterate through jagged array values and indices in Python - Stack Overflow
1 Matrix (Jagged Array) for in loop initialization More on stackoverflow.com
🌐 stackoverflow.com
April 13, 2017
python - How to make 2D jagged array using NumPy - Stack Overflow
You can't. This is a 1d array containing lists; more like a list of lists. But what do you expect to do with such an array? ... NumPy does not support jagged arrays natively. More on stackoverflow.com
🌐 stackoverflow.com
Top answer
1 of 2
3

Your array is 2x2:

In [298]: A
Out[298]: 
array([[array([1, 2, 3]), array([4, 5])],
       [array([6, 7, 8, 9]), array([10])]], dtype=object)

While A+A works, boolean tests have not been implemented for this kind of array:

In [299]: A>4
...
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

I'm going to flatten A because it makes it easier to compare with list operations:

In [301]: A1=A.flatten()

In [303]: A1+A1
Out[303]: 
array([array([2, 4, 6]), array([ 8, 10]), array([12, 14, 16, 18]),
       array([20])], dtype=object)

In [304]: [a+a for a in A1]
Out[304]: [array([2, 4, 6]), array([ 8, 10]), array([12, 14, 16, 18]), array([20])]

In [305]: timeit A1+A1
100000 loops, best of 3: 6.85 µs per loop

In [306]: timeit [a+a for a in A1]
100000 loops, best of 3: 9.09 µs per loop

The array operation is a bit faster than a list comprehension. But if I first turn the array into a list:

In [307]: A1l=A1.tolist()

In [308]: A1l
Out[308]: [array([1, 2, 3]), array([4, 5]), array([6, 7, 8, 9]), array([10])]

In [309]: timeit [a+a for a in A1l]
100000 loops, best of 3: 5.2 µs per loop

times improve. This is a good indication that the A1+A1 (or even A+A) is using a similar sort of iteration.

So the straight forward way of performing your A,B calculation is

In [310]: A2=[a[a>4] for a in A1]
In [311]: B=[a+a for a in A2]
In [312]: B
Out[312]: [array([], dtype=int32), array([10]), array([12, 14, 16, 18]), array([20])]

(we can convert to/from arrays and lists as needed).

A numpy array stores its data a flat databuffer, and uses the shape and strides attributes to quickly calculate the location of any element, regardless of the dimensions. The fast array operations use compiled code that rapidly steps though the databuffers of arguments, performing the operations element by element (or some other combination).

A dtype object array also has the flat databuffer, but the elements are pointers to lists or arrays elsewhere. So while it can index individual elements quickly, it still has to perform a Python call(s) to access the arrays. So especially when the array is 1d, it is virtually the same as a flat list with the same pointers.

Multidimensional object arrays are nicer than nested lists. You can reshape them, access elements (A[1,3] v Al[1][3]), transpose them, etc. But when it comes to iterating through all the subarrays they don't offer much of a benefit.

Looking again at your 2d array:

In [315]: timeit A+A
100000 loops, best of 3: 6.93 µs per loop  # 6.85 for A1+A1 (above)

In [316]: timeit [[j+j for j in i] for i in A]
100000 loops, best of 3: 17.1 µs per loop

In [317]: Al = A.tolist()

In [318]: timeit [[j+j for j in i] for i in Al]
100000 loops, best of 3: 7.01 µs per loop    # 5.2 for A1l flat list

Basically the same time for summing the array and iterating through the equivalent nested list.

2 of 2
0

The performance of numpy jagged array may not be optimal, but there are enough reasons to believe that it should be much better than using python nested list. As explained in your earlier post:

On principle you should have some performance bonus because every element is a numpy array. So you just need a 2 dimensional loop rather than a 3D loop (if you store every number in nested lists). Also it always saves you lots of memory allocation time to avoid using python list.

Here is a simple test:

import time,sys,random
import numpy as np
rand = np.random.rand
L = np.array([[rand(100), rand(200)],[rand(400), rand(300)]], dtype=object)
L1 = [random.random() for i in range(1000)]
arrFunc = np.vectorize(lambda x:x[x>0.3],otypes=[np.ndarray])

start = time.time()
if sys.argv[1]=='np':
  for i in range(100000):
    B=i*L
else:
  for i in range(100000):
    B=[i*x for x in L1]

end = time.time()
print ('Arithmetic Op: ', end-start)


start = time.time()
if sys.argv[1]=='np':
  for i in range(100000):
    B=arrFunc(L)
else:
  for i in range(100000):
    B=[x for x in L1 if x<0.3]
end = time.time()
print ('Indexing       ', end-start)

Result:

> python testNpJarray.py np
Arithmetic Op:  3.9719998836517334
Indexing        8.079999923706055

> python testNpJarray.py list
Arithmetic Op:  53.289000034332275
Indexing        52.10899996757507

This test may not be quite fare because the outter numpy array is quite small, you are welcome to change the size to fit into your application and tell us the results.

🌐
LinkedIn
linkedin.com › all topics › technology › data science › data engineering
Programming Foundations: Data Structures Online Class | LinkedIn Learning, formerly Lynda.com
While structures like arrays and queues are sometimes taken for granted, a deeper understanding is vital for any programmer who wants to know what's going on "under the hood" and understand how the choices they've made impact the performance and efficiency of their applications. In this course, Kathryn Hodge provides an in-depth overview of the most essential data structures for modern programming in Python.
Published: September 19, 2023
🌐
Reddit
reddit.com › r/learnpython › numpy stack jagged arrays – can i make this code cleaner?
r/learnpython on Reddit: NumPy stack jagged arrays – can I make this code cleaner?
September 4, 2015 - Subreddit for posting questions and asking for general advice about your python code. ... I have 3 NumPy arrays of different lengths and want to combine them into a matrix, filling in 0s to make them equal length. I've used a rather dirty for-loop solution – is there a better way to do this? #this matrix may be jagged.
Find elsewhere
🌐
GitHub
github.com › scikit-hep › awkward-0.x
GitHub - scikit-hep/awkward-0.x: Manipulate arrays of complex data structures as easily as Numpy. · GitHub
The shape and stride are constants, enforcing a regular layout. Awkward's JaggedArray is a generalization of Numpy's rank-2 arrays—that is, arrays of arrays—in that the inner arrays of a JaggedArray may all have different lengths.
Starred by 214 users
Forked by 38 users
Languages: Python 63.7% | Jupyter Notebook 36.3%
🌐
Awkward-array
awkward-array.org › doc › main › getting-started › jagged-ragged-awkward-arrays.html
Jagged, Ragged, Awkward Arrays! — Awkward Array 2.9.1 documentation
Hint: the final result should be a jagged array, just like muon_pt, but with fewer lists and fewer items in those lists.
🌐
GitHub
github.com › scikit-hep › ragged
GitHub - scikit-hep/ragged: Manipulating ragged arrays in an Array API compliant way. · GitHub
See Awkward Array papers and presentations for more. ... ragged is a pure-Python library that only depends on awkward (which, in turn, only depends on numpy and a compiled extension). In principle (i.e.
Author: scikit-hep
🌐
Gauravpandey
gauravpandey.com › wordpress
Gauravpandey
May 8, 2012 - To iterate over a every single element of a Jagged Array in Python, you will need to override the default iterator func.
🌐
EDUCBA
educba.com › home › software development › software development tutorials › python tutorial › multidimensional array in python
Multidimensional Array in Python | Creating a Multidimensional List
April 17, 2023 - Multidimensional arrays in Python ... of the multidimensional list ) with each element inner array capable of storing independent data from the rest of the array with its own length also known as a jagged array, which cannot ...
Address: Unit no. 202, Jay Antariksh Bldg, Makwana Road, Marol, Andheri (East),, 400059, Mumbai
🌐
Annasguidetopython
annasguidetopython.com › python3 › data structures › arrays-creating-a-jagged-array
Arrays - Creating a jagged array in Python
May 12, 2023 - In this example, we’ve modified the second row of the jagged array by adding an element to it. In conclusion, jagged arrays are a useful data structure for dealing with varying amounts of data.
🌐
Navaneeth Suresh
navaneeth.net › blog › indexing-ragged-arrays-in-python
Indexing Ragged Arrays in Python • Navaneeth Suresh
June 2, 2021 - This post is going to be a small attempt from my side to understand indexing ragged arrays and making that work with Python. Indexing a data structure is accessing its elements by making memory efficient. A ragged array or a jagged array is an array of arrays which the member arrays can be ...
🌐
GitHub
github.com › topics › jagged-array
jagged-array · GitHub Topics · GitHub
December 2, 2022 - python json numpy pandas data-analysis numba apache-arrow columnar-format ragged-array cern-root rdataframe scikit-hep jagged-array
🌐
Scientific Python
discuss.scientific-python.org › contributor & development discussion
Best practices regarding accepting ragged arrays - Contributor & Development Discussion - Scientific Python
November 17, 2023 - I will repeat the question that I made on the Discord here, as I think it is better for future reference. I want to ask what is the best practice for working with ragged arrays in the presence of arbitrary array backends (because I use the Python array API standard).
🌐
Procodebase
procodebase.com › article › jagged-arrays
Jagged Arrays
In Python, jagged arrays can be easily represented using lists.