Удалить некоторые из списка f#

#list #f#

#Список #f#

Вопрос:

У меня есть такой список

 let data = [{ A = "one"; B = 2020; C = Some 5L; D = None };
            { A = "two"; B = 2020; C = None; D = Some 3L}]
 

как мне заменить C = Some 5L; на C = 5;

я хочу вот так ->

 [{ A = "one"; B = 2020; C = 5; D = null };
 { A = "two"; B = 2020; C = null; D = 3}]
 

я пытался let newData = data |> List.choose id
Это не работает.

Комментарии:

1. То, что вы хотите, не имеет никакого смысла. Почему вы хотите, чтобы это было так?

2. эти записи поступают из базы данных C или D может быть нулевым или некоторым значением int

3. Тогда в вашем желаемом результате вы должны иметь C = null вместо C = None и вы можете сопоставить его, как предлагает ajuch, с int? просто установите для него значение null, когда оно равно none.

4. Проблема в том, что у вас не может быть 2 разных типа в списке. None имеет тип Option<int> , тогда 5 как это тип int . Они не могут быть в одном списке. Записи имеют разные типы.

5. Вместо nullable в F # вы используете Option тип. Это правильный способ обработки возможных пропущенных значений. В противном случае ваш код небезопасен.

Ответ №1:

Вы можете использовать System.Nullable для представления типов с нулевым значением, которые C # должен распознавать. Также вам нужно будет создать отдельный тип записи для представления ваших данных с полями с возможностью обнуления. Я могу себе представить, что вам нужно совершить такую транзакцию при выходе из мира F # и входе в C #.

 type A  = { A:string; B: int; C: int64 option; D: int64 option}
type T  = { A2:string; B2: int; C2: System.Nullable<int64>; D2: System.Nullable<int64>}
let data = [{ A = "one"; B = 2020; C = Some 5L; D = None };
            { A = "two"; B = 2020; C = None; D = Some 3L}]

let getNullable (x: int64 option) =
  match x with
  | Some v -> System.Nullable(v)
  | None -> System.Nullable()


let nullablData (data : A list)= 
  data |> List.map (fun x -> {A2 = x.A; B2 = x.B; C2 = getNullable(x.C); D2 = getNullable(x.D)})

let res=  nullablData data

//result
//val res : T list = [{A2 = "one"; B2 = 2020; C2 = 5L; D2 = null;};
//                    {A2 = "two"; B2 = 2020; C2 = null; D2 = 3L;}]
 

Ответ №2:

На самом деле вы хотите отобразить элементы списка в другой тип. Поскольку запись, которую вы используете внутри списка, выглядит так

 type X = {
  A: string
  B: int
  C: int option
  D: obj option
}
 

и вы хотите иметь

 type Y = {
  A: string
  B: int
  C: int
  D: obj option
}
 

(обратите внимание на тип для C), вам нужно преобразовать элементы списка с List.map помощью функции, которая отображает тип X в тип Y.

 data |> List.map (fun x -> { A = x.A; B = x.B; C = (x.C |> Option.defaultValue 0); D = x.D})
 

Вы должны правильно обработать C=None случай, присвоив ему значение по умолчанию.

Комментарии:

1. Я обновил вопрос. У меня не может быть 0, когда оно равно none.

2. В этом случае вы можете использовать List.choose вместо List.map , чтобы исключить элементы, которые имеют None . Функция будет такой: (fun x -> if x.C.IsNone then None else Some { A = .x.A ... где остальное то же самое.