FSharpList<string> para IList<string> para XML
Pergunta
Usando um código para converter IList<T>
para um FSharpList<T>
em seguida, gravar a lista de valores de um XML.
public static class Interop
{
public static FSharpList<T> ToFSharpList<T>(this IList<T> input)
{
return CreateFSharpList(input, 0);
}
private static FSharpList<T> CreateFSharpList<T>(IList<T> input, int index)
{
if(index >= input.Count)
{
return FSharpList<T>.Empty;
}
else
{
return FSharpList<T>.Cons(input[index], CreateFSharpList(input, index + 1));
}
}
}
Eu uso o código acima para fazer a minha própria lista
var fsharp_distinct = distinctWords.ToFSharpList();
var distinct_without_stopwords = Module2.stopword(fsharp_distinct);
foreach (string wd in distinct_without_stopwords)
colwordfreq.Root.Add(new XElement(wd));
De fato, o XML está escrito também, mas pouco antes de sair do laço dá um System.NullReferenceException
.Mas quando um F# retornado de uma função Tuple<string, int>
usando o mesmo código, eu não tinha problemas para escrever a Tupla de valores de um XML.
EDITAR: Eu não estava correta na questão acima.A ponto nulo exceção, na verdade, veio este código:
foreach (Tuple<string, int> pair in list2)
colwordfreq.Root.Element(pair.Item1).Add(new XElement("freq", pair.Item2));
Mas quando eu adicionei a condição
if (colwordfreq.Root.Element(pair.Item1) != null)
Ele não dá a essa exceção.
Solução
O seu exemplo é um pouco incompleto, mas se colwordfreq.Root.Element(pair.Item1)
retorna null
para algumas palavras, isso provavelmente significa que você não adicionar esse elemento anteriormente.Talvez você precisa adicionar elementos de escrever algo como:
foreach (Tuple<string, int> pair in list2)
colwordfreq.Root.Add // Add element to the root
(new XElement(pair.Item1, // with the name of the word
new XElement("freq", pair.Item2))); // ... and the count
De lado, quando você está chamando F# o código do C#, vale a pena conferir o F# componente diretrizes de design.Uma das sugestões de lá (o que eu recomendo fortemente seguir) é para evitar o uso de F# tipos específicos (como FSharpList
) a partir do C#.Estas são realmente concebido para o F# e são difíceis de usar corretamente a partir do C#.
Você pode adicionar um simples F# função de wrapper que expõe a funcionalidade usando IEnumerable
, que será muito mais fácil usar a partir do C#:
let rec stopword a =
match a with
|"the"::t |"this"::t -> stopword t
|h::t ->h::(stopword t)
|[] -> []
module Export =
let StopWord (inp:seq<_>) =
(inp |> List.ofSeq |> stopword) :> seq<_>
Em seguida, você pode apenas chamar Export.StopWord(en)
C# sem explicitamente lidar com F# listas.