2010-12-02 19 views
2

J'ai une liste de chaînes qui sont sous la forme de XxX où X sont des nombres jusqu'à 4 chiffres (ce sont des tailles d'image en (pixels) x (pixels)).Comment puis-je trier mes tailles d'image sur les deux coordonnées?

Par exemple:

["192x192","64x84","96x96","64x64","292x192","32x32","64x12"] 

L'utilisation d'un mysort fonction qui est juste tri par insertion qui ne regarde que le nombre jusqu'à x:

mysort [] = [] 
mysort [x] = [x] 
mysort (x:xs) = insert (mysort xs) 
    where insert [] = [x] 
      insert (y:ys) | takeUntilX x <= takeUntilX y = x : y : ys 
         | otherwise = y : insert ys 

Je reçois ceci:

["192x192","292x192","32x32","64x84","64x64","64x12","96x96"] 

Ce qui n'est que partiellement trié, tous les "64x **" triés restants dans leur ordre d'origine mais je veux qu'ils soient aussi triés si je reçois ceci:

["192x192","292x192","32x32","64x12","64x64","64x84","96x96"] 

Quelle serait une meilleure solution - fonction de modification mysort ou d'écrire une nouvelle fonction qui trie la liste partiellement triés? Pouvez-vous me donner l'idée de base que je pourrais faire?

Répondre

8
import Data.List 
import Data.List.Split 

res = map (intercalate "x") . sort . map (splitOn "x") 

J'utilise Data.List.Split de http://hackage.haskell.org/package/split

+0

:) Il y a toujours quelqu'un qui utilise Haskell au jour le jour (contrairement à moi). Fair-play - +1 –

+0

ne fonctionne pas; tri: ["192x192", "64x184", "96x96", "64x64", "292x192", "32x32", "64x12"] donne ["192x192", "292x192", "32x32", "64x12", " 64x184 "," 64x64 "," 96x96 "] 64 sont faux – ostochast

+0

@ Possible: Voir ci-dessous - J'ai compris de quoi vous parliez (n'était pas clair pour moi avant). –

0

EDIT: Corrigé - J'ai compris ce que vous vouliez dire.

Je séparer les préoccupations - (1) analyser les chaînes pour obtenir les dimensions; (2) trier les dimensions comme bon vous semble; (3) convertir les dimensions en chaînes. En d'autres termes:

import List 

stringToDim :: String -> (String,String) 
stringToDim s = (a,c) 
    where (a,b) = break (== 'x') s 
      c = drop 1 b 

dimToString :: (String,String) -> String 
dimToString (x,y) = x ++ "x" ++ y 

dimsort :: [String] -> [String] 
dimsort = map dimToString . sort . map stringToDim 
3

Pour les besoins futurs à l'esprit, vous pouvez aussi:
1. convertir vos données en tuples par exemple (64, 64)
2. utiliser tri intégré. Il fait exactement ce que vous voulez

Je suppose que dans le futur vous utiliserez les données comme entiers, ainsi les convertir le plus tôt possible pourrait vous épargner beaucoup d'ennuis dans le futur.

br,
Juha

0

Ok, voici la solution finale, je suis content même si ce n'est pas ce que j'Originaly demandé. copie modifiée de max taldykin:

res x = map (intercalate "x") $ map myshow $ sort $ map (readAsInt) $ map (splitOn "x") x 

readAsInt [x,y] = [read x :: Int, read y ::Int] 
myshow [x,y] = [show x, show y] 

input: ["192x192","64x184","96x96","64x64","292x192","32x32","64x12"] 
output: ["32x32","64x12","64x64","64x184","96x96","192x192","292x192"] 

Bien qu'il does't donner [ "192x192", "292x192", "32x32", "64x12", "64x64", "64x184", "96x96"] il est encore ok pour ce que j'avais en tête.

+0

ouais, ma faute. Il est plus concis de changer "sort" en "sortBy (en comparant readAsInt)". "comparison" vient de Data.Ord –

+0

... et "readAsInt [x, y] = (lire x :: Int, lire y :: Int)" avec tuple comme résultat –