2015-03-11 5 views
0

Я новичок в F #, и в настоящее время я очень незнакомо с .NET API.F #: Использование Enumerable.GroupBy в F #

Я хочу использовать .NET Enumerable.GroupBy method в программе F #. Вот соответствующий пример из моего кода:

let atLeast2Values (key , values) = 
    Seq.length values > 1 

let findGroupsOfTwoOrMore (directory: string) = 
    let getPath = snd 
    let getLength = fst 

    let fileNameLengthPairs = new DirectoryInfo(directory) 
           |> getFileLengthAndFileNameTuples 

    fileNameLengthPairs.GroupBy(keySelector = getLength, elementSelector = getPath) 
    |> Seq.filter atLeast2Values 

К сожалению, работает этот код возвращает следующее сообщение об ошибке:

Program.fs (37,51): FS0001 ошибки: Это выражение, как ожидается, имеют тип
Func<(int64 * string),'a>
, но здесь имеет тип
'b * 'c -> 'b

Как я могу устранить эту ошибку?

EDIT: Вот функция getFileLengthAndFileNameTuples:

let rec getFileLengthAndFileNameTuples (dirInfo: DirectoryInfo) = 
     seq { 
      let nameLengthPairs = dirInfo.GetFiles() 
            |> Seq.map (fun fileInfo -> (fileInfo.Length, fileInfo.FullName)) 

      yield! nameLengthPairs 

      let subFolders = dirInfo.GetDirectories() 

      for subFolder in subFolders do 
       yield! getFileLengthAndFileNameTuples subFolder 
     } 
+0

Каков тип 'fileNameLengthPairs'? можете ли вы добавить функцию getFileLengthAndFileNameTuples? Вам лучше использовать groupby, предоставляемый последовательностью (Seq.groupBy https://msdn.microsoft.com/en-us/library/ee370445.aspx) –

+0

Привет, Томас. Я добавил функцию в соответствии с запросом. Я использую Enumerable.GroupBy, потому что хочу указать селектор элементов. Seq.groupBy в F # не выполняет то же самое. Благодарю. –

+0

'GroupBy (keySelector = Func <_, _> (getLength), elementSelector = Func <_, _> (getPath))' интересно, похоже, что вы получаете правильный 'Func', когда вы не используете именованные аргументы:' GroupBy (getLength, getPath) ' –

ответ

2

Предполагая, что fileNameLengthPairs имеет тип:

val fileNameLengthPairs : seq<int * string>

Вы можете использовать код, приведенный ниже.

fileNameLengthPairs 
|> Seq.groupBy (fun (length, _) -> length) 
|> Seq.filter (fun (key, value) -> (Seq.length value) > 1) 

Это лучше использовать Seq.groupBy из F # модуля, так как это может быть частично применен и код выглядит более свободно и функциональным.

+1

' groupBy' хороший. Если вам нужна более высокая производительность, вам может потребоваться использовать linq 'toLookup'. – mydogisbox

Смежные вопросы