I have python code that uses arcpy.SearchCursor to look for unique values in a field (Native_Species, in my case), and put them into a list. Then I use list comprehension to remove None values, sort the list, and print. This code works.
# Create empty list, use .SearchCursor to populate list with unique values
myList = []
rows = arcpy.SearchCursor(monitoring)
for row in rows:
if row.Native_Species not in myList:
myList.append(row.Native_Species)
# Use list comprehension to remove None values in list
res = [i for i in myList if i]
# Sort list and print
res.sort()
print(*res, sep = '\n')
I would like to put this code into a function, where I can list only unique values across multiple fields in a given feature class. This is what I have tried:
def listUnique(fc, fields):
myList = []
with arcpy.da.SearchCursor(fc, fields) as cursor:
for row in cursor:
if row.fields not in myList:
myList.append(row.fields)
res = [i for i in myList if i]
res.sort()
print(*res, sep = '\n')
This gives me an error "'tuple' object has no attribute 'fields'".
How should I put my working code into a function, where I can specify a given input feature class, and a list of fields within that feature class, and get back a list of only unique values across those fields?
Thank you!
The output is not real pretty. Might be more useful to create a unique value list for every feature class column. Hopefully this will give you some ideas to get what you need.
import arcpy
# set the workspace to the geodatabase the feature class is in
arcpy.env.workspace = r'\path\to\your\geodatabase.gdb'
def uniqueValues(fc):
# create a list of unique values from all rows and columns in a feature class
#create an empty list to store all values in the feature class
tableList = []
#Get all values in the feature class and append them to tableList
fcList = arcpy.ListFeatureClasses(fc)
for fc in fcList:
with arcpy.da.SearchCursor(fc, "*") as cursor:
for row in cursor:
for value in row:
tableList.append(value)
print('The list length of all values is ' + str(len(tableList)))
# Create an empty list to store the unique values in the feature class
uniqueList = []
# use set to drop duplicates
uniqueSet = set(tableList)
print('The list length of unique values is ' + str(len(uniqueSet)))
# put the items from the set back into a list. add all values to the list as strings to avoid data type problems
for item in uniqueSet:
uniqueList.append(str(item))
# remove none values from the list
uniqueList = [i for i in uniqueList if i]
# sort the list
uniqueList = sorted(uniqueList)
print(*uniqueList, sep = '\n')
# call the function and enter the name of the feature class as the parameter
uniqueValues('Enter Feature Class Name')
Related
I have a list of personal data(id_code,birth_year,born_in) and i want to sort the any arrays in list but i have a problem in this work.
my list data :
data = [
'id_code:3211238576;birth_year:1350;born_in:Boushehr',
'id_code:9801233575;born_in:Argentina;birth_year:1360',
'born_in:Portugal;id_code:0219206431;birth_year:1358',
'id_code:0021678913;born_in:Shiraz;birth_year:1120',
'id_code:1101102135;born_in:Gilan;birth_year:1152',
]
The code I wrote and has an bug:
for i in data:
s = ''.join(sorted(i))
print(s)
my code output:
01112233355678:::;;B___abbcddeeehhhiiinnooorrrrstuy
00112333556789:::;;A___aabbcddeeeghiiiinnnnoorrrrtty
00111223345689:::;;P___aabbcddeeghiiilnnooorrrrttuy
00011112236789:::;;S___aabbcddeehhiiiinnoorrrrtyz
00111111122355:::;;G___aabbcddeehiiiilnnnoorrrty
But! The code to i want to have in output(True answer):
id_code:3211238576,born_in:Boushehr,birth_year:1350
id_code:9801233575,born_in:Argentina,birth_year:1360
id_code:0219206431,born_in:Portugal,birth_year:1358
id_code:0021678913,born_in:Shiraz,birth_year:1120
id_code:1101102135,born_in:Gilan,birth_year:1152
Please help me to solve this problem
Assuming you want your fields to be in specific order, try this one: (I put comments in code for clarification):
data = [
'id_code:3211238576;birth_year:1350;born_in:Boushehr',
'id_code:9801233575;born_in:Argentina;birth_year:1360',
'born_in:Portugal;id_code:0219206431;birth_year:1358',
'id_code:0021678913;born_in:Shiraz;birth_year:1120',
'id_code:1101102135;born_in:Gilan;birth_year:1152',
]
def sorter(x: str):
# getting the field name
field = x.split(':')[0]
# returning it's index from "sorted_by" list
return sorted_by.index(field)
# The index of these fields will be used for sorting in "sorter" function.
sorted_by = ['id_code', 'born_in', 'birth_year']
result = []
for item in data:
# splitting the fields
splited = item.split(';')
splited.sort(key=sorter)
# building the line back and append it
result.append(';'.join(splited))
for i in result:
print(i)
output :
id_code:3211238576;born_in:Boushehr;birth_year:1350
id_code:9801233575;born_in:Argentina;birth_year:1360
id_code:0219206431;born_in:Portugal;birth_year:1358
id_code:0021678913;born_in:Shiraz;birth_year:1120
id_code:1101102135;born_in:Gilan;birth_year:1152
Now you can easily change the fields order in sorted_by list and see the result.
Try
out = [';'.join(reversed(sorted(x.split(';')))) for x in data]
print(out)
This takes every element of the data list and splits it in three strings, each of which contains one of the three attributes. Then, it arranges the three strings in reversed alphabetical order and joins them back into one string, separated by ';'
New to python and for this example list
lst = ['<name>bob</name>', '<job>doctor</job>', '<gender>male</gender>', '<name>susan</name>', '<job>teacher</job>', '<gender>female</gender>', '<name>john</name>', '<gender>male</gender>']
There are 3 categories of name, job, and gender. I would want those 3 categories to be on the same line which would look like
<name>bob</name>, <job>doctor</job>, <gender>male</gender>
My actual list is really big with 10 categories I would want to be on the same line. I am also trying to figure out a way where if one of the categories is not in the list, it would print something like N/A to indicate that it is not in the list
for example I would want it to look like
<name>bob</name>, <job>doctor</job>, <gender>male</gender>
<name>susan</name>, <job>teacher</job>, <gender>female</gender>
<name>john</name>, N/A, <gender>male</gender>
What would be the best way to do this?
This is one way to do it. This would handle any length list, and guarantee grouping no matter how long the lists are as long as they are in the correct order.
Updated to convert to dict, so you can test for key existence.
lst = ['<name>bob</name>', '<job>doctor</job>', '<gender>male</gender>', '<name>susan</name>', '<job>teacher</job>', '<gender>female</gender>', '<name>john</name>', '<gender>male</gender>']
newlst = []
tmplist = {}
for item in lst:
value = item.split('>')[1].split('<')[0]
key = item.split('<')[1].split('>')[0]
if '<name>' in item:
if tmplist:
newlst.append(tmplist)
tmplist = {}
tmplist[key] = value
#handle the remaining items left over in the list
if tmplist:
newlst.append(tmplist)
print(newlst)
#test for existance
for each in newlst:
print(each.get('job', 'N/A'))
df_store_index_list = df_store.index.tolist()
df_store_column_list = df_store[column].tolist()
list_to_be_returned = []
for i in range(len(df_store_index_list)):
list_to_be_returned.append([df_store_index_list[i], df_store_column_list[i]])
# return list_to_be_returned
return [[df_store_index_list[i], df_store_column_list[i]] for i in range(len(df_store_index_list)) ] not working!!!!
I have a function that returns a two-dimensional list.
Problem: the list comprehension on the last line is giving me an error saying "df_store_index_list is not defined".
Solution: I created my own list (list_to_be_returned) and did a custom for loop and it's working fine. It has a value (list_to_be_returned). But I was just wondering, why is the list comprehension not working?
here is the complete code
#classmethod
def store_specific_info_string(cls, store_name, column, ascending=False):
"""
Brief
- filter for specific store
Description
- obtain sum of column based on specific `Store_Name`
Parameter
- store_name : inside the `Store_Name` column
- ascending : True or False
- column : sum of what column? (Total_Sales, Total_Profit)
Return Value(s)
- tuple of name(Item_Description) and sum of column passed based on name.
"""
# filter the store by store name
df_store = cls.dataframe[ cls.dataframe[ "Store_Name" ] == store_name]
df_store = df_store.groupby("Item_Description").sum()[[column]]
# sort them by the column(integer)
df_store.sort_values(column,ascending=ascending ,inplace=True)
df_store_index_list = df_store.index.tolist()
df_store_column_list = df_store[column].tolist()
list_to_be_returned = []
for i in range(len(df_store_index_list)):
list_to_be_returned.append([df_store_index_list[i], df_store_column_list[i]])
return list_to_be_returned
# return [[df_store_index_list[i], df_store_column_list[i]] for i in range(len(df_store_index_list)) ] not working!!!!
here is a pdb initiated
inside pdb
Based on your comment it seems that you really want the list of list format with a list comprehension. Here is another way to do your list comprehension (but that doesn't explain why yours didn't work)
column_serie = df_store[column]
[[idx, value] for idx,value in column_serie.iteritems()]
Im trying to sort my list which contains of 3 nested lists: paths, file names and finally file creation time. So I want to sort them to be able to get the latest files.
So Ive seen people been using lambda for this, but I dont feel comfortable using those and kind of dont get how to the sorting with that works.
I think the best way is just to switch the list components, but this does not work:
class FILE:
PATH = 0
NAME = 1
DATE = 2
mayaFiles = [[],[],[]]
mayaFiles[FILE.DATE] = [0,56,3,12,7,35,16]
doSwitch = True
while (doSwitch):
for ma in range(0, len(mayaFiles[FILE.DATE])-1):
doSwitch = False
doSwitch = mayaFiles[FILE.DATE][ma] > mayaFiles[FILE.DATE][ma+1]
hi = mayaFiles[FILE.DATE][ma]
lo = mayaFiles[FILE.DATE][ma+1]
if doSwitch:
mayaFiles[FILE.DATE][ma] = lo
mayaFiles[FILE.DATE][ma+1] = hi
else:
break
print mayaFiles[FILE.DATE]
Assuming these lists are already aligned, you'll have a much easier time by combing the there separate lists into a list of tuples arranged by your sort order. the namedtuple construct in the collections module is great for this sort of thing. I'm assuming you can get your data into three lists: paths, dates and names. I'm supplying some dummy data here so you can see what I'm assuming.
names = "a.ma", "b.ma", "c.ma", "d.ma"
paths = "c:/test", "c/test", "c:/other", "d:/extra"
dates = "17-01-01", "16-01-01", "17-02-01", "17-06-30"
# this creates a namedtuple, which is a
# mini-class with named fields that otherwise
# works like a tuple
from collections import namedtuple
record = namedtuple("filerecord", "date name path")
# in real use this should be a list comp
# but this is easier to read:
records = []
for date, name, path in zip(dates, names, paths):
records.append(record(date, name, path))
records.sort(reverse=True)
for item in records:
print item
# filerecord(date='17-06-30', name='d.ma', path='d:/extra')
# filerecord(date='17-02-01', name='c.ma', path='c:/other')
# filerecord(date='17-01-01', name='a.ma', path='c:/test')
# filerecord(date='16-01-01', name='b.ma', path='c/test')
You could sort on other fields using the 'key' argument to sort():
records.sort(key=lambda k: k.name)
for item in records:
print item
# filerecord(date='17-01-01', name='a.ma', path='c:/test')
# filerecord(date='16-01-01', name='b.ma', path='c/test')
# filerecord(date='17-02-01', name='c.ma', path='c:/other')
# filerecord(date='17-06-30', name='d.ma', path='d:/extra')
Trying to get something to work where I randomize 4 objects in an array and randomly select one of those. I need to be able to get the original index number for that chosen object back. Any idea on how I should write this as short as possible?
arrayRandomSongs = []
arrayChosen = []
trackChosen = ""
def randomizeArray(self):
del self.arrayRandomSongs[:] # wipes array of all contents without making a new one
self.arrayRandomSongs = self.arraySongs[:]
random.shuffle(self.arrayRandomSongs)
def chooseListing(self):
del self.arrayChosen[:] # same here
for i in xrange(4):
self.arrayChosen.append(self.arrayRandomSongs[i])
del self.arrayRandomSongs[0:3]
def chooseTrack(self):
self.trackChosen = random.choice(self.arrayChosen)
As you can see I would like to select the arayChosen index number for the trackChosen object, but since it's randomized I don't see how I could do that.
You will have to keep track of indexes before randomizing. Then access the index value from the tracking list after randomizing and selecting an element from the randomized list.
For getting index of an element in list you can do <list>.index(<element>).
Explanation:
Create a copy of arrayRandomSongs before shuffling its elements.
original_arrayRandomSongs = arrayRandomSongs[:]
After getting the value of trackChosen by doing random.choice, use that value to get its index in original list by doing
original_arrayRandomSongs.index(self.trackChosen)
Well you could do something like this
list = [4,1,3,2]
list_with_indices = [(num,i) for i, num in enumerate(list)]
shuffle(list_with_indices)
essentially you keep track of the original index.