1
$\begingroup$

Is it possible to change the word order of a phrase by creating a list of possible values/variables and using the Sort function?

I want a specific word order always. $(a>b>c>d)$ But the values represented will change example to example. Associations may be what I'm actually trying to create, I'm not sure of the correct term.

Some examples of variables/associations:

a={"Left" or "Right" or "Top" or "Bottom"}
b={"Red" or "Blue" or "Green" or "Yellow"}
c={"Closing" or "Rolling" or "Running" or "Cleaning"}
d={"Paper" or "Note" or "Cat" or "Dog"}

Then I want to create a function:

neworder=Sort[a,b,c,d]

Then apply the function to a phrase (that has already been StringSplit):

neworder["Running","Dog","Blue"]

out = {"Blue","Running","Dog"}

Another example:

neworder["Red","Paper","Cleaning","Top"]

out = {"Top","Red","Cleaning","Paper"}

Is it possible to us Sort/SortBy in this manner? I know there are a few options in the way Sort works, but hadn't seen this method before. (Sorting a phrase by WordData, "PartsOfSpeech" is also on my radar, because that is essentially how I'm defining my variables/associations.)

$\endgroup$
  • $\begingroup$ Aren't "Left" and"Blue" the same part of speech? $\endgroup$ – BlacKow Apr 8 '16 at 15:30
  • $\begingroup$ @BlacKow Correct. Maintaining control of the difference between directional and color words felt important when I began thinking about this, so that's why the sorting by PartsOfSpeech is kind of an after thought. I'm working through your suggestion below, and it seems to be on the same track as I was hoping this could work. $\endgroup$ – JonathanKolar Apr 8 '16 at 15:36
2
$\begingroup$

Straightforward way:

a = {"Left", "Right", "Top", "Bottom"};
b = {"Red", "Blue", "Green", "Yellow"};
c = {"Closing", "Rolling", "Running", "Cleaning"};
d = {"Paper", "Note", "Cat", "Dog"};
weights = 
  Transpose@
     Flatten[#, 
      1] &@(Transpose@{#1, ConstantArray[#2, Length@#1]} & @@@ {{a, 
       1}, {b, 2}, {c, 3}, {d, 4}});


sort[phrase_, weights_] := 
  SortBy[phrase, First@Pick[weights[[2]], weights[[1]], #] &];
sort[{"Red", "Paper", "Cleaning", "Top"}, weights]

{"Top", "Red", "Cleaning", "Paper"}

Or if you want to deal with "unknown" words by placing them in the end.

sort[phrase_, weights_] := 
  SortBy[phrase, 
   If[# == {}, Infinity, First[#]] &@
     Pick[weights[[2]], weights[[1]], #] &];
sort[{"Red", "blah", "Paper", "Cleaning", "Top", "babah"}, weights]

{"Top", "Red", "Cleaning", "Paper", "babah", "blah"}

You can of course define weights any way you want. I just followed your data.

Update If your phrase consists of words from list a only, the order will be changed, which I think is bad. So I modified the sorting function:

sort3[phrase_, weights_] := Module[{phind},
   phind = MapIndexed[{#1, First@#2} &, phrase];
   First@Transpose@
     SortBy[phind, 
      Function[x, 
         If[x == {}, 1^-10 #[[2]] + 10^10, First[x] + 1^-10 #[[2]]]]@
        Pick[weights[[2]], weights[[1]], #[[1]]] &]
   ];

So now compare

sort[{"Red", "Green", "Blue", "Yellow"}, weights]
(*{"Blue", "Green", "Red", "Yellow"}*)
sort3[{"Red", "Green", "Blue", "Yellow"}, weights]
(*{"Red", "Green", "Blue", "Yellow"}*)

sort[{"Red", "Green", "bub", "Blue", "ash", "Yellow"}, weights]
(*{"Blue", "Green", "Red", "Yellow", "ash", "bub"}*)
sort3[{"Red", "Green", "bub", "Blue", "ash", "Yellow"}, weights]
(*{"Red", "Green", "Blue", "Yellow", "bub", "ash"}*)

Now the sorting function accounts for position in the original phrase.

$\endgroup$
  • $\begingroup$ I was able to replicate your code and results successfully. You anticipated a follow up question I was going to have with your explanation of how to deal with unknown words. Bravo. How many examples could I have in my variables? Such as: a={100 examples}... zz={100 examples} $\endgroup$ – JonathanKolar Apr 8 '16 at 15:52
  • $\begingroup$ @JonathanKolar You can have weights list of any length. Keep in mind that Pick will traverse the the whole list. So if you want to be efficient you can explore SelectFirst instead of Pick to see if it's better. Also at some point it makes sense to sort your weights and then perform search in sorted list. $\endgroup$ – BlacKow Apr 8 '16 at 16:19
  • $\begingroup$ @JonathanKolar Updated the sorting slightly, so it won't change order of words having same weight. $\endgroup$ – BlacKow Apr 8 '16 at 18:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.