Home » Extract Valid Time Entries

Extract Valid Time Entries

Extract the valid times from the given strings. Time appears as HH:MM HH: This will either be 1 digit or 2 digits (will range between 0 to 23) MM: This will always be two digits (will range between 00 to 59) Note – If a portion of string is already used, then nothing from that portion can be reused. Ex- 13:518:14 = Since 13:51 has been used, next answer would be 8:14 not both 18:14 and 8:14

📌 Challenge Details and Links
ExcelBI Power Query Challenge Number: 155
Challenge Difficulty: ⭐️⭐️⭐️⭐️
📥Download Sample File
📥Link to the solutions on LinkedIn

Solving the challenge of Extract Valid Time Entries with Power Query

Power Query solution 1 for Extract Valid Time Entries, proposed by Zoran Milokanović:
let
  Source = Excel.CurrentWorkbook(){[Name = "Input"]}[Content], 
  C = each try Time.FromText(_, [Format = "H:mm", Culture = "en-US"]) otherwise null, 
  P = (i, o) =>
    let
      M = (s, c) => Text.Middle(i, s, c), 
      L = Text.Length, 
      p = Text.PositionOf(i, ":"), 
      N = each p - _ >= 0 and List.Contains({"0" .. "9"}, Text.At(i, p - _)), 
      s = (if N(2) then M(p - 2, 2) else if N(1) then M(p - 1, 1) else "")
        & (
          let
            r = M(p, 3)
          in
            if L(r) = 3 then r else ""
        ), 
      d = if o = "" then o else ", "
    in
      if p = - 1 then o else @P(M(p + 3, L(i)), o & (if C(s) <> null then d & s else "")), 
  S = Table.AddColumn(Source, "Expected Answer", each P([String], ""))
in
  S
Power Query solution 2 for Extract Valid Time Entries, proposed by Alejandro Simón 🇵🇦 🇪🇸:
let
  Origen = Excel.CurrentWorkbook(){[Name = "Tabla1"]}[Content], 
  Sol = Table.AddColumn(
    Origen, 
    "Answer", 
    each 
      let
        a = Text.SplitAny([String], Text.Combine({"A" .. "Z", "a" .. "z", "_", "$"})), 
        b = List.Select(a, each _ <> "" and Text.Contains(_, ":")), 
        c = List.Combine(
          List.Transform(b, each try Splitter.SplitTextByRepeatedLengths(5)(_) otherwise _)
        ), 
        d = List.Select(
          c, 
          each try Value.Is(Time.From(_), Time.Type) and Text.Length(_) > 3 otherwise false
        )
      in
        Text.Combine(d, ", ")
  )
in
  Sol
Power Query solution 3 for Extract Valid Time Entries, proposed by Luan Rodrigues:
let
  Fonte = Tabela1, 
  res = Table.AddColumn(
    Fonte, 
    "Personalizar", 
    each 
      let
        a = List.Zip({{"a" .. "z", "A" .. "Z"}, List.Repeat({" "}, 52)}), 
        b = Text.Combine(List.ReplaceMatchingItems(Text.ToList([String]), a)), 
        c = Text.SplitAny(b, ":_$ "), 
        d = List.Select(
          List.TransformMany(
            c, 
            each Text.Split(Text.Middle(_, 0, 2) & " " & Text.Middle(_, 2, 2), " "), 
            (x, y) => y
          ), 
          each _ <> " " and _ <> ""
        ), 
        e = List.Select(
          List.Split(d, 2), 
          (x) => Number.From(x{0}) <= 23 and Number.From(x{1}) <= 59 and Text.Length(x{1}) = 2
        ), 
        f = Text.Combine(List.Transform(e, each Text.Combine(_, ":")), ", ")
      in
        f
  )
in
  res
Power Query solution 4 for Extract Valid Time Entries, proposed by Eric Laforce:
let
  Source = Excel.CurrentWorkbook(){[Name = "tData155"]}[Content], 
  Result = Table.AddColumn(
    Source, 
    "Hours", 
    each 
      let
        l = List.Generate(
          () => [s = Text.Select([String], {"0" .. "9", ":"}) & " ", r = {}], 
          each Text.Length([s]) > 0, 
          each 
            let
              h  = Text.End(Text.BeforeDelimiter([s], ":"), 2), 
              m  = Text.Start(Text.AfterDelimiter([s], ":"), 2), 
              hm = if (Text.Contains([s], ":")) then h & ":" & m else [s]
            in
              [s = Text.AfterDelimiter([s], hm), r = [r] & {hm}]
        ), 
        s = List.Select(List.Last(l)[r], each try Time.From(_) is time otherwise false)
      in
        Text.Combine(s, ", ")
  )
in
  Result
Power Query solution 5 for Extract Valid Time Entries, proposed by Arden Nguyen, CPA:
let
  Source = Excel.CurrentWorkbook(){[Name = "Table1"]}[Content], 
  T = List.Transform, 
  col = Table.AddColumn(
    Source, 
    "Custom", 
    each 
      let
        a = List.RemoveItems(
          Splitter.SplitTextByAnyDelimiter({"a" .. "z", "A" .. "Z", "$", "_"})([String]), 
          {""}
        ), 
        b = Text.Combine(
          List.RemoveItems(
            T(
              a, 
              (x) =>
                [
                  _a = Text.PositionOf(x, ":", Occurrence.All), 
                  _b = T(_a, each _ + 3), 
                  _c = Splitter.SplitTextByPositions({0} & _b)(x), 
                  _d = T(
                    _c, 
                    each 
                      if Text.Length(Text.AfterDelimiter(_, ":")) = 2 then
                        try Time.ToText(Time.From(_), [Format = "hh:mm"]) otherwise null
                      else
                        null
                  ), 
                  _e = Text.Combine(_d, ", ")
                ][_e]
            ), 
            {""}
          ), 
          ", "
        )
      in
        b
  )
in
  col

Solving the challenge of Extract Valid Time Entries with Excel

Excel solution 1 for Extract Valid Time Entries, proposed by Bo Rydobon 🇹🇭:
=MAP(A2:A11&"a",LAMBDA(a,LET(m,MID(a,SEQUENCE(LEN(a)),1),c,CONCAT(m&DROP(REPT("a",VSTACK(0,0,m)=":"),-2)),w,TEXTSPLIT(c,,TEXTSPLIT(c,":",SEQUENCE(10)-1,1)),
TEXTJOIN(", ",,REPT(w,(w=TEXT(w,"h:mm"))+(w=TEXT(w,"hh:mm"))>0)))))
Excel solution 2 for Extract Valid Time Entries, proposed by محمد حلمي:
=MAP(A2:A10,LAMBDA(a,LET(v,UNIQUE(TOCOL(FIND(":",
a,SEQUENCE(20)),2)),r,IF(1+ISNUMBER(-MID(a,v-2,1))
-IFERROR(VSTACK(2,1+(DROP(v,1)-DROP(v,-1)>4)),2),
1,2),x,MID(a,v-r,r),u,MID(a,v+1,2),TEXTJOIN(", ",,IFERROR(
IFS(--x<24,x)&":"&IFS((LEN(u)=2)*(--u<60),u),"")))))
Excel solution 3 for Extract Valid Time Entries, proposed by Ziad A.:
=ARRAYFORMULA(TRIM(REGEXREPLACE(A2:A10,"((?:[01]?[0-9]|2[0-3]):[0-5][0-9])|.","$1 ")))

Solving the challenge of Extract Valid Time Entries with Python in Excel

Python in Excel solution 1 for Extract Valid Time Entries, proposed by Abdallah Ally:
import pandas as pd
import re
file_path = r'C:UsersaallyDownloadsPower_Query_Challenge_155.xlsx'
df = pd.read_excel(file_path, usecols=[0, 3])
# Create a function to extract valid times from a string
def extract_valid_times(col):
 valid_times = [x for x in re.findall(r'd{1,2}:d{2}', col) 
 if int(x.split(':')[0]) < 24 and int(x.split(':')[1]) < 60]
 return ', '.join(valid_times)
# Create a new column containing valid times extracted from a string 
df['My Answer'] = df['String'].apply(extract_valid_times)
# Replace empty string values with nan values
df['My Answer'] = df['My Answer'].replace('', float('nan'))
print(df)
                    
                  
Python in Excel solution 2 for Extract Valid Time Entries, proposed by JvdV -:
import re
[', '.join(re.sub(r'2[4-9]|[3-9]d:|(dd?:[0-5]d)|.',r'1 ',s).split())for s in xl("A2:A10")[0]] 
https://regex101.com/r/E4LOsm/1
                    
                  

Solving the challenge of Extract Valid Time Entries with R

R solution 1 for Extract Valid Time Entries, proposed by Konrad Gryczan, PhD:
library(tidyverse)
library(readxl)
input = read_excel("Power Query/PQ_Challenge_155.xlsx", range = "A1:A10")
test = read_excel("Power Query/PQ_Challenge_155.xlsx", range = "D1:D10")
extract = function(string) {
 subs = string %>% 
 str_extract_all("\d{1,2}\:\d{2}") %>%
 unlist()
 subs = purrr::map_chr(subs, function(x) {
 ifelse(
 as.numeric(strsplit(x, ":")[[1]][1]) %in% 0:23 & as.numeric(strsplit(x, ":")[[1]][2]) %in% 0:59,
 x,
 NA_character_
 )
 }) %>%
 na.omit() %>%
 str_c(collapse = ", ")
 return(subs)
}
result = input %>% 
 mutate(extracted = map_chr(String, extract),
 extracted = ifelse(extracted == "", NA_character_, extracted))
                    
                  

&&&

Leave a Reply