问题
This question follows on from my previous question How to transform a CSV into several lists (applescript)?
I have a csv file with about 4000 lines. I import it and make each line into an item of a list, I then make each line it's own list of items.
eg: (I am using numbers but the data I have contains text as well and most of the entries are more than 1 char, some entries are also blank)
1,2,3,4,5,6
6,5,4,3,2,1
7,8,9,0,7,6
3,4,4,5,3,1
becomes
{"1,2,3,4,5,6","6,5,4,3,2,1","7,8,9,0,7,6","3,4,4,5,3,1"}
becomes
{{"1","2","3","4","5","6"}{"6","5","4","3","2","1"}{"7","8","9","0","7","6"}{"3","4","4","5","3","1"}}
now what I would like to be able to do is the following:
Delete certain items from each list, so for example I want to delete the second Item from Each list, that's "2", "5", "8" and "4"
Run calculations on certain items, so for example I want to multiply item 5 by 2
Also some of the numbers in my data have the +11 or + 17 at the end of them, I would like to know how to replace that with the matching amount of zeros, so for example if i had 5002+6 I would want to make it into 5002000000
Current code is:
-- Choosing your file
set csvDevices to "testfile.csv"
-- Reading file to memory
set csvDevices to read csvDevices
-- Creating Records (Single Lines)
set csvDevicesRecords to paragraphs of csvDevices
-- Remove Title Line
set csvDevicesRecords to rest of csvDevicesRecords
-- Make each line into a list
set csvDevicesValues to {}
set AppleScript's text item delimiters to ","
repeat with i from 1 to length of csvDevicesRecords
set end of csvDevicesValues to text items of (item i of csvDevicesRecords)
end repeat
set AppleScript's text item delimiters to ""
I hope the above all makes sense.
回答1:
It's really not hard if you write yourself a subroutine to do the stuff for you. Here's the 3 you requested. You'll need to add other subroutines so you can do other math operations (add, subtract, and divide). Just duplicate the multiplyItemNumberByValue() subroutine and change the operator to the appropriate one and it should work with no further changes.
Good luck.
set listOfLists to {{"1", "2+2", "3", "4", "5", "6"}, {"6", "5", "4", "3", "2", "1"}, {"7", "8", "9", "0", "7", "6"}, {"3", "4", "4", "5+3", "3", "1"}}
-- before performing any other operation, expand all zeros
set listOfLists to expandZeros(listOfLists)
-- remove item 2 from every sublist
set listOfLists to removeItemNumber(listOfLists, 2)
-- multiply item 1 of every sublist by 5
set listOfLists to multiplyItemNumberByValue(listOfLists, 1, 5)
(****************** SUBROUTINES ******************)
on multiplyItemNumberByValue(listOfLists, itemNumber, theValue)
set newList to {}
repeat with i from 1 to count of listOfLists
set thisList to item i of listOfLists
set thisItem to item itemNumber of thisList
set newValue to (thisItem as number) * theValue
set item itemNumber of thisList to (newValue as text)
set end of newList to thisList
end repeat
return newList
end multiplyItemNumberByValue
on removeItemNumber(listOfLists, itemNumber)
set newList to {}
repeat with i from 1 to count of listOfLists
set thisList to item i of listOfLists
if itemNumber is equal to 1 then
set newSublist to items 2 thru end of thisList
else if itemNumber is equal to (count of thisList) then
set newSublist to items 1 thru (itemNumber - 1) of thisList
else
set newSublist to items 1 thru (itemNumber - 1) of thisList & items (itemNumber + 1) thru end of thisList
end if
set end of newList to newSublist
end repeat
return newList
end removeItemNumber
on expandZeros(listOfLists)
set newList to {}
repeat with i from 1 to count of listOfLists
set thisList to item i of listOfLists
set newSublist to {}
repeat with j from 1 to count of thisList
set subItem to item j of thisList
if subItem contains "+" then
set x to offset of "+" in subItem
if x is equal to 0 or x is equal to 1 or x is equal to (count of subItem) then
set end of newSublist to subItem -- do nothing
else
set a to text 1 thru (x - 1) of subItem
set b to text (x + 1) thru end of subItem
repeat (b as number) times
set a to a & "0"
end repeat
set end of newSublist to a
end if
else
set end of newSublist to subItem -- do nothing
end if
end repeat
set end of newList to newSublist
end repeat
return newList
end expandZeros
Here's the other math subroutines...
on divideItemNumberByValue(listOfLists, itemNumber, theValue)
set newList to {}
repeat with i from 1 to count of listOfLists
set thisList to item i of listOfLists
set thisItem to item itemNumber of thisList
set newValue to (thisItem as number) / theValue
set item itemNumber of thisList to (newValue as text)
set end of newList to thisList
end repeat
return newList
end divideItemNumberByValue
on addValueToItemNumber(listOfLists, itemNumber, theValue)
set newList to {}
repeat with i from 1 to count of listOfLists
set thisList to item i of listOfLists
set thisItem to item itemNumber of thisList
set newValue to (thisItem as number) + theValue
set item itemNumber of thisList to (newValue as text)
set end of newList to thisList
end repeat
return newList
end addValueToItemNumber
on subtractValueFromItemNumber(listOfLists, itemNumber, theValue)
set newList to {}
repeat with i from 1 to count of listOfLists
set thisList to item i of listOfLists
set thisItem to item itemNumber of thisList
set newValue to (thisItem as number) - theValue
set item itemNumber of thisList to (newValue as text)
set end of newList to thisList
end repeat
return newList
end subtractValueFromItemNumber
回答2:
Nigel Garvey's CSV-to-list converter is the best I have seen.
You can call it like this:
set filePath to "/Users/You/Desktop/myCsv.csv"
set csvData to do shell script "cat " & quoted form of filePath
set csvDevicesLists to csvToList(csvData, {trimming:true})
--> {{"1", "2", "3", "4", "5", "6"}, {"6", "5", "4", "3", "2", "1"}, {"7", "8", "9", "0", "7", "6"}, {"3", "4", "4", "5", "3", "1"}}
You can pad zeros like this:
set xxx to {{"1", "2", "3+2", "4", "52+3", "6"}, {"6", "5", "4+5", "3", "2", "1"}}
repeat with i from 1 to count of xxx
if (item i of xxx as text) contains "+" then
set temp to {}
repeat with anItem in item i of xxx
set end of temp to (do shell script "echo " & quoted form of anItem & " | sed s/+/*10^/ | bc")
end repeat
set item i of xxx to temp
end if
end repeat
return xxx
ASObjC Runner provides some good tools for manipulating lists as well.
回答3:
It would be easier to use Ruby or Python (or almost any other language):
"1,2,3+11,4,5,6
6,5,4,3,2,1+17".split("\n").each { |n|
n.gsub!(/\+(\d+)/, "0" * $1.to_i)
c = n.split(",")
c[4] = c[4].to_i * 5
c.delete_at(1)
puts c.join(",")
}
来源:https://stackoverflow.com/questions/14963605/how-to-read-modify-remove-items-lists-contained-in-a-list-in-applescript