Best way to sort text on iOS?

I have a list of comma-separated items in Drafts that I want to sort alphabetically. What’s the best way to do that on iOS?

Pythonista should be able to do this fairly easily.

1 Like

Since it’s already in Drafts, roughly (since I don’t own or know how Drafts automation works) you can convert a comma separated string into an array like this:

var array = string.split(",");

Source

Then, you can just call the array.sort() method.

W3Schools Example

And then if you wanted to convert back to a string just call array.toString()

W3Schools Example

Edit: Tried JSON Parse and didn’t work. Fixed to use string split()

All Together Example:
let fruits = "Banana,Orange,Apple,Mango";
let array = fruits.split(",");
array.sort();
let result = array.toString();
console.log(result); // Returns Apple,Banana,Mango,Orange

Run Here

2 Likes

From the options I see in Drafts, it looks like I would use the Share button to process (maybe sending it to a Workflow).

Is the code you’re providing something I would put into Pythonista?

No that’s for Drafts. That’s Javascript syntax. It is very similar for Pythonista.

If you wanted to use Pythonista, it would look something like this. You would need to make it into a share sheet extension and use the appex module to get the text passed in from Drafts or your selection.

Edit: Here’s using appex and clipboard module.

Code
import appex
import clipboard

text = appex.get_text()

if not text:
	print('No input text found. Use this script from the share sheet in an app like Notes.')
		return

array = text.split(",")
array.sort()
result = ','.join(map(str, array))
clipboard.set(result)

The benefit of doing it in Drafts is editing in place. Using Pythonista, you’d have delete and paste from the clipboard after running the script.

Copy / import the CSV-text to Numbers (or Excel), sort there and export back out?

I’ve taken a small look at Drafts. It looks like you would need to create a new action.
You’d use the Editor module found here.

So, you’d use the code from above, and replace
let fruits = ... with let fruits = editor.getSelectedText()
and console.log(result) with editor.setSelectedText(result).

It would probably be smart to include a check for no text passed in like shown in the example for the Editor module above.

I’d start with this existing action:

Sort

You should just need to replace the \n characters with commas…

4 Likes

While I like the geeky answer of reaching for Pythonista there is actually a super simple way to do this and that’s using Workflow. I have a “Sort Clipboard” workflow that would fit the bill.
The steps are as follows “Get Clipboard > Transform Text [sort lines - ascending] > Copy to Clipboard”

This short piece of JavaScript code to make your own Drafts action solves your issue.

// Alpha sort a list separated by commas, periods, semi-colons,
// and/or colons. Removes extra whitespace.

var isSelEmpty = editor.getSelectedText().length == 0;
var txt = isSelEmpty ? editor.getText() : editor.getSelectedText();

var txt = txt.replace(/([,;:\.\n])( +)?/g, '\n');
var lines = txt.split('\n').sort();
var txt = lines.join(', ');

if (isSelEmpty)
    editor.setText(txt);
else
    editor.setSelectedText(txt);
editor.activate();

The first two lines retrieve the text from the Drafts edition. (If no text is selected within Drafts editor, it selects all the text.)

The third line replaces any commas, periods, semi-colons, or colons with a new line character. It also removes any extra white space.

The fourth line splits the text into lines based on the new character and sorts them.

The fifth line rejoins everything into a single line, separating each item with a comma and space.

The last set of lines saves it all back in the Drafts editor.

1 Like

I don’t have that action…

You can create it yourself. That’s why I wrote it out longhand.

If your list is in Drafts and you are not explicitly needing it somewhere else that is better, then the best approach is always going to involve staying in Drafts as it will be quicker and less jarring from a user experience point of view.

It’s very much as @dustinknopoff describes.

However, even CSV can be tricky. What if there’s whitespace around your comma? What if there’s commas in your data items and you have wrapped some of them in double quotes. As a result I think the more general requirement is trickier than first glance.

I believe the following Drafts 5 action (you can install it into Drafts 5) should take care of the above and perhaps some edge cases besides.

The action has two steps. The first script step just separates out a parameter to enable wrapping of data items in double quotes and is enabled by default. The second step does all the processing.

Script contents
//STEP 1
//Set to true to wrap (delimit) all CSV entries in double quotes
//Set to false to not do this
bDoubleQuotes = true;

// STEP 2
// Source = http://www.greywyvern.com/?post=258
String.prototype.splitCSV = function(sep)
{
	for (var foo = this.split(sep = sep || ","), x = foo.length - 1, tl; x >= 0; x--)
	{
		if (foo[x].replace(/"\s+$/, '"').charAt(foo[x].length - 1) == '"')
		{
			if ((tl = foo[x].replace(/^\s+"/, '"')).length > 1 && tl.charAt(0) == '"')
			{
				foo[x] = foo[x].replace(/^\s*"|"\s*$/g, '').replace(/""/g, '"');
			}
			else if (x)
			{
				foo.splice(x - 1, 2, [foo[x - 1], foo[x]].join(sep));
			}
			else foo = foo.shift().split(sep).concat(foo);
		}
		else foo[x].replace(/""/g, '"');
	}
	return foo;
};

// Sort a CSV string and optionally wrap all content in double quotes
// If there's any chance your content contains non-separator comms, you must set this to true
function sortCSV(p_strCSV, p_bIncludeDoubleQuotes)
{
	if (p_bIncludeDoubleQuotes == true)
	{
		return "\"" + p_strCSV.splitCSV().sort().join("\",\"") + "\"";
	}
	else
	{
		return p_strCSV.splitCSV().sort().join(",")
	}

}

// Sort a selected CSV string (or an entire draft if there is no selection) and optionally wrap all content in double quotes
// If there's any chance your content contains non-separator comms, you must set this to true
function sortSelectedCSV(p_bIncludeDoubleQuotes)
{
	if (editor.getSelectedText.length != 0)
	{
		editor.setSelectedText(sortCSV(editor.getSelectedText(), p_bIncludeDoubleQuotes));
	}
	else
	{
		editor.setText(sortCSV(editor.getText(), p_bIncludeDoubleQuotes));
	}
}

sortSelectedCSV(bDoubleQuotes);

Hope that helps.