Страницы

Поиск по вопросам

суббота, 21 марта 2020 г.

OpenCV java как разделить слитные контуры

#java #алгоритм #opencv






У меня есть проект по распознаванию чисел. 

Я хочу выделить каждую цифру, но есть близко находящиеся числа, которые я хочу разделить.
Как можно разделить такие числа?
    


Ответы

Ответ 1



В данном случае должна помочь морфологическая операция opening - комбинация эрозии и дилатации. Первый этап удалит отдельные точки и тонкие мостики, второй восстановит общие очертания в несколько сглаженном виде без этих деталей. Конечно, при этом какие-то фигуры могут рассыпаться на части (например, из за дефектов в правой пятёрке). Нужно смотреть, поможет ли предварительный closing для уничтожения дефектов, или приведёт к неубиваемым мостикам-спайкам. Вообще для таких изображений анализируют объекты и строят решётку - цифры же определённого размера и положение их не случайно, в таком случае разделение производится по границам ячеек/ограничивающих прямоугольников.

Ответ 2



Я не знаю как называется этот способ, он основан на построении гистограммы изображения, и поиске локальных минимумов, но сначала нужно найти и залить все замкнутые области. let img = new Image(); img.crossOrigin = 'anonymous'; img.src = 'https://i.imgur.com/EqAIRNx.png'; let srcCtx = src.getContext('2d'), gistCtx = gist.getContext('2d'); img.onload = function() { src.width = gist.width = img.width; src.height = gist.height = img.height; srcCtx.drawImage(img, 0, 0); let imgData = srcCtx.getImageData(0, 0, img.width, img.height) let gistData = Array(img.width).fill(0); for(var x = 0; x10 ? 1 : 0; gistData.forEach((e,i) => line(gistCtx, i, e)) gistCtx.strokeStyle = srcCtx.strokeStyle = 'red'; extrem(gistData, 12).min .map(e => Math.floor(e[0]/2 + e[1]/2)) .forEach((e, i) => { line(gistCtx, e, img.height) line(srcCtx, e, img.height) }) } function line(ctx, x, h) { ctx.beginPath(); ctx.moveTo(x, img.height); ctx.lineTo(x, img.height - h); ctx.stroke(); } function extrem(y, eps) { let s,M,m,j, i=0, min=[], max=[], greater = a => a >= M - eps, lesser = a => a <= m + eps; for (; i < y.length; i++) { if (s && M - eps <= y[i]) M = Math.max(M, y[i]) else if (!s && m + eps >= y[i]) m = Math.min(m, y[i]) else if (s) m = iter(max, greater) else M = iter(min, lesser) } return {min, max}; function iter(arr, cond) { j = i - 1; while (cond(y[j])) j--; arr.push([j, i]); s = !s; return y[i]; } }

PS: похоже что при помощи нахождения минимумов построчно и вращении исходного изображения можно еще найти на сколько нужно повернуть картинку, чтобы текст встал четко по горизонтали.

Какая максимальная длина идентификаторов и можно ли ее изменить?

#sql #oracle #plsql #oracle11g #oracle12c


Использую версию 11g и хотел бы давать имена длина которых более чем 30 символов.
Мне известно, что макс. длина в 11g только 30 символов:

create table tab (very_very_very_very_very_very_very_very_LongColumnName number)



  ORA-00972: identifier is too long


Возможно ли как-то изменить макс. длину? 

Какая макс. длина идентификаторов в версии 12c?
    


Ответы

Ответ 1



Имена объектов БД 11g, а также в версии 12cR1, ограничены 30 байтами (в single-byte кодировке это эквивалентно 30 символам). Можно ли это изменить? Нет, не существует способа измененить это, чтобы можно было пользоваться именами обьектов БД длиной более чем 30 байтов. Ограничение в 30 байт было впервые снято во втором выпуске 12c ( 12cR2), и если значение параметра инициаллизации COMPATIBLE установленно в 12.2 и выше, то макс. длина идентификаторов может быть до 128 байт. SQL> show parameters compat NAME TYPE VALUE ------------------------------------ ----------- ------------------------------ compatible string 12.2.0 SQL> create table tab (very_very_very_very_very_very_very_very_LongColumnName number); Table TAB created. SQL> declare very_very_very_very_very_very_very_very_LongVariableName number; begin null; end; / PL/SQL procedure successfully completed. Источник ответа: @Nick Krasnov.

Конвертация pd.Series в pd.Dataframe определенного формата

#python #python_3x #pandas #dataframe #pivot


Существует одномерный массив b

b = pd.Series(
[110.0, 120.0, Horsepower]
[150.0, 175.0, Horsepower]
[1351.0, 1601.0, Capacity]
[12.0, 14.0, Metric Tons]
[1601.0, 1751.0, Capacity])
Name: fiProductClassDesc, dtype: object



Первая цифра списка - минимальное значение
Вторая цифра списка - максимальное значение
Третье значение - название категории (всего 4 шт.)


Необходимо создать из него a = pd.Dataframe, всего 8 колонок, где для каждой строки,
значения будут присвоены только тем колонкам, для которых совпадает название категории
и лэйбла колонки. Остальные 0. 

Digging Depth_min   Digging Depth_max   Metric Tons_min Metric Tons_max Horsepower_min
 Horsepower_max  Capacity_min    Capacity_max
0   0   0   0   110 120 0   0
0   0   0   0   150 175 0   0
0   0   0   0   0   0   1351    1601
0   0   12  14  0   0   0   0
0   0   0   0   0   0   1601    1751

    


Ответы

Ответ 1



Я бы делал это так: x = pd.DataFrame(b.to_list()).rename(columns={0: "min", 1: "max"}) res = x.pivot_table(index=x.index, columns=2, fill_value=0).swaplevel(axis=1) res.columns = res.columns.map("_".join) res = res.sort_index(axis=1, ascending=False) результат: In [115]: res Out[115]: Metric Tons_min Metric Tons_max Horsepower_min Horsepower_max Capacity_min Capacity_max 0 0 0 110 120 0 0 1 0 0 150 175 0 0 2 0 0 0 0 1351 1601 3 12 14 0 0 0 0 4 0 0 0 0 1601 1751 PS думаю добавить нулевые столбцы Digging Depth_min и Digging Depth_max проблем не составит пошаговое решение: In [116]: pd.DataFrame(b.to_list()).rename(columns={0: "min", 1: "max"}) Out[116]: min max 2 0 110.0 120.0 Horsepower 1 150.0 175.0 Horsepower 2 1351.0 1601.0 Capacity 3 12.0 14.0 Metric Tons 4 1601.0 1751.0 Capacity In [117]: x.pivot_table(index=x.index, columns=2, fill_value=0).swaplevel(axis=1) Out[117]: 2 Capacity Horsepower Metric Tons Capacity Horsepower Metric Tons max max max min min min 0 0 120 0 0 110 0 1 0 175 0 0 150 0 2 1601 0 0 1351 0 0 3 0 0 14 0 0 12 4 1751 0 0 1601 0 0 In [120]: res Out[120]: Capacity_max Horsepower_max Metric Tons_max Capacity_min Horsepower_min Metric Tons_min 0 0 120 0 0 110 0 1 0 175 0 0 150 0 2 1601 0 0 1351 0 0 3 0 0 14 0 0 12 4 1751 0 0 1601 0 0 In [121]: res.sort_index(axis=1, ascending=False) Out[121]: Metric Tons_min Metric Tons_max Horsepower_min Horsepower_max Capacity_min Capacity_max 0 0 0 110 120 0 0 1 0 0 150 175 0 0 2 0 0 0 0 1351 1601 3 12 14 0 0 0 0 4 0 0 0 0 1601 1751

Ошибка Python Pandas - The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all()

#python #pandas


Жестко затупил на контрольном задании на курсе ЯндексПрактикум "Аналитик данных"

Дана таблица:

df = pd.read_csv('/datasets/music_project.csv')


Задание:

Утро понедельника и вечер пятницы — разная музыка или одна и та же?

Ищем ответ на вопрос, какие жанры преобладают в разных городах в понедельник утром
и в пятницу вечером. Есть предположение, что в понедельник утром пользователи слушают
больше бодрящей музыки (например, жанра поп), а вечером пятницы — больше танцевальных
(например, электронику).

Получим таблицы данных по Москве moscow_general и по Санкт-Петербургу spb_general.

# получение таблицы moscow_general из тех строк таблицы df, 
# для которых значение в столбце 'city' равно 'Moscow'
moscow_general = df[df['city'] == 'Moscow']


# получение таблицы spb_general
# для которых значение в столбце 'city' равно 'Saint-Petersbur'
spb_general = df[df['city'] == 'Saint-Petersburg']


Создаём функцию genre_weekday(), которая возвращает список жанров по запрошенному
дню недели и времени суток с такого-то часа по такой-то.

def genre_weekday(df, day, time1, time2):
    genre_list =  df[ (df['weekday'] == day) & (df['time']>time1) & (time2>df['time'])]
    genre_list_sorted = genre_list.groupby('genre_name')['genre_name'].count().sort_values(ascending
= False).head(10) 
    return genre_list_sorted

# объявление функции genre_weekday() с параметрами df, day, time1, time2

# в переменной genre_list сохраняются те строки df, для которых одновременно:
# 1) значение в столбце 'weekday' равно параметру day,
# 2) значение в столбце 'time' больше time1 и
# 3) меньше time2.

# в переменной genre_list_sorted сохраняются в порядке убывания  
# первые 10 значений Series, полученной подсчётом числа значений 'genre_name'
# сгруппированной по столбцу 'genre_name' таблицы genre_list

# функция возвращает значение genre_list_sorted


Cравниваем полученные результаты по таблице для Москвы и Санкт-Петербурга в понедельник
утром (с 7 до 11) и в пятницу вечером (с 17 до 23).

Утро понедельника в Москве

# <вызов функции для утра понедельника в Москве (вместо df таблица moscow_general)>
genre_weekday(moscow_general, 'Monday', '07:00:00', '11:00:00')


Результат:

genre_name
pop            781
dance          549
electronic     480
rock           474
hiphop         286
ruspop         186
world          181
rusrap         175
alternative    164
classical      157
Name: genre_name, dtype: int64


Утро понедельника в СПб

# <вызов функции для утра понедельника в Петербурге (вместо df таблица spb_general)>
genre_weekday(spb_general, 'Monday', '07:00:00', '11:00:00')


Результат:

genre_name
pop            218
dance          182
rock           162
electronic     147
hiphop          80
ruspop          64
alternative     58
rusrap          55
jazz            44
classical       40
Name: genre_name, dtype: int64


Вечер пятницы в Москве

# <вызов функции для вечера пятницы в Москве>
genre_weekday(moscow_general, 'Friday', '17:00:00', '23:00:00')


Результат:

genre_name
pop            713
rock           517
dance          495
electronic     482
hiphop         273
world          208
ruspop         170
alternative    163
classical      163
rusrap         142
Name: genre_name, dtype: int64


Вечер пятницы в СПб

# <вызов функции для вечера пятницы в Питере>
genre_weekday(spb_general, 'Friday', '17:00:00', '23:00:00')


Результат:

genre_name
pop            256
rock           216
electronic     216
dance          210
hiphop          97
alternative     63
jazz            61
classical       60
rusrap          59
world           54
Name: genre_name, dtype: int64


Популярные жанры в понедельник утром в Питере и Москве оказались похожи: везде, как
и предполагалось, популярен поп. Несмотря на это, концовка топ-10 для двух городов
различается: в Питере в топ-10 входит джаз и русский рэп, а в Москве жанр world.

В конце недели ситуация не меняется. Поп-музыка всё так же на первом месте. Опять
разница заметна только в концовке топ-10, где в Питере пятничным вечером тоже присутствует
жанр world

Конец задания

Вроде все сходится с написанными Яндексом подсказками и выводами, но при сдаче задания
на проверку дает ошибку The truth value of a Series is ambiguous. Use a.empty, a.bool(),
a.item(), a.any() or a.all().

Суть ошибки вроде бы понял, но не понимаю в какой момент она возникает.

Если это может помочь, ссылка на диск со всеми заданиями. cell In [48]:
https://yadi.sk/d/xO0cm83NXVyPJA
    


Ответы

Ответ 1



Возможно, проблема в этой строке: genre_list = df[ (df['weekday'] == day) & (df['time']>time1) & (time2>df['time'])] Попробуйте заменить на какой-нибудь из этих вариантов: genre_list = df.query('weekday == @day and @time2 > time > @time1') genre_list = df.loc[(df['weekday'] == day) & (df['time'].between(time1, time2, inclusive=False))]

Ответ 2



У меня валидатор принял такой вариант: genre_list = df[ (df['weekday'] == day) & (df['time'] > time1) & (df['time'] < time2)] возможно ему важно в каком порядке идут сравниваемые величины..

Matplotlib.pyplot.subplots() не отображает графики seaborn на разных сетках

#python #matplotlib #seaborn


Есть непрерывная переменная df_train_tr['TransactionAmt'], хочу построить плотность
распределения переменной в изначальном формате и после применения функции log.

fig, ax = plt.subplots(1, 2, figsize=(11, 5), sharey=True)
plt.style.use('classic')
fig.patch.set_facecolor('xkcd:white')

ax[0]= sns.distplot(df_train_tr[df_train_tr['TransactionAmt'] <= 1000]['TransactionAmt'])
ax[0].set_xlabel('TransactionAmt', fontsize=16)
ax[0].set_title('Transaction Value distibution')
ax[0].set_ylabel('Probability', fontsize=16)
ax[0].axis(xmin=0)

ax[1] = sns.distplot(np.log(df_train_tr[df_train_tr['TransactionAmt'] <= 1000]['TransactionAmt']))
ax[1].set_xlabel('TransactionAmt', fontsize=16)
ax[1].set_title('Transaction Value distibution')
ax[1].set_ylabel('Probability', fontsize=16)
ax[1].axis(xmin=0)

plt.show()



 Данный код рисует все на одном графике и, самое интересное, переменная ax состоит
из двух одинаковых объектов

[,
 ],
          dtype=object)


Хотя до исполнения строчек с ax[0] и ax[1] объекты разные

[
 ]


Переписал, используя вместо sns.distplot() plt.hist()

ax[0].hist(df_train_tr[df_train_tr['TransactionAmt'] <= 1000]['TransactionAmt'])
#ax[0]= sns.distplot(df_train_tr[df_train_tr['TransactionAmt'] <= 1000]['TransactionAmt'])
ax[0].set_xlabel('TransactionAmt', fontsize=16)
ax[0].set_title('Transaction Value distibution')
ax[0].set_ylabel('Probability', fontsize=16)
ax[0].axis(xmin=0)

ax[1].hist(np.log(df_train_tr[df_train_tr['TransactionAmt'] <= 1000]['TransactionAmt']))
#ax[1] = sns.distplot(np.log(df_train_tr[df_train_tr['TransactionAmt'] <= 1000]['TransactionAmt']))
ax[1].set_xlabel('TransactionAmt', fontsize=16)
ax[1].set_title('Transaction Value distibution')
ax[1].set_ylabel('Probability', fontsize=16)
ax[1].axis(xmin=0)

plt.show()


И получил то, что хотел (y_axis - sic!)

Можно ли переписать код, чтобы получить второй вариант, но используя Seaborn?


    


Ответы

Ответ 1



Укажите явно axis, с которой работаете: import matplotlib.pyplot as plt import seaborn as sns import numpy as np fig, axs = plt.subplots(1, 2, figsize=(11, 5), sharey=True) plt.style.use('classic') fig.patch.set_facecolor('xkcd:white') x = np.random.randn(100) ax=axs[0] ax= sns.distplot(x, ax=ax) # <-- здесь ax.set_xlabel('TransactionAmt', fontsize=16) ax.set_title('Transaction Value distibution') ax.set_ylabel('Probability', fontsize=16) ax.axis(xmin=0) ax=axs[1] ax = sns.distplot(np.log(abs(x)), ax=ax, hist=False) # здесь я еще и гистограмму # отключил. для наглядности ax.set_xlabel('TransactionAmt', fontsize=16) ax.set_title('Transaction Value distibution') ax.set_ylabel('Probability', fontsize=16) ax.axis(xmin=0) plt.show()

Стилизация по PEP8 в python

#python_3x


По PEP8 название фунции должны быть нижним регистром и отделяться нижним анрскором,
но сама стандартная библиотека не соблюдает этого стандарта? также и относится к классам. 
    


Ответы

Ответ 1



Встроенные типы не являются классами, подобными обычным пользовательским классам. До версии питона 2.2 такие имена как list, tuple, int были просто функциями, поэтому и писались с маленькой буквы. В отличие от пользовательских классов, от встроенных типов нельзя было наследоваться. Были ещё небольшие отличия от обычных классов. Начиная с версии 2.2 встроенные типы и пользовательские классы почти полностью уравняли в правах, но имена остались старыми, чтобы не ломать уже существующий код. По поводу названий методов в PEP8 написано: mixedCase is allowed only in contexts where that's already the prevailing style (e.g. threading.py), to retain backwards compatibility mixedCase допускается только в тех случаях, когда это уже преобладающий стиль (например, threading.py), чтобы сохранить обратную совместимость То есть так уже было до того, как PEP8 был написан, и, соответственно, опять-таки не стали ничего исправлять, чтобы не ломать уже существующий код.

Couldn't match type `Int' with `[Char]'

#haskell #haskell_stack


Начал изучать haskell по книге.

В процессе написал и попытался скомпилировать следующий код:

{-# LANGUAGE MultiWayIf #-}


module Main where

calculateTime :: Int -> Int
calculateTime timeInS =
    let threshold  = 40
        correction = 120
    in
    if  | timeInS < threshold -> timeInS + correction
        | otherwise ->
            let delta = 8
            in
            timeInS + delta + correction

main :: IO()
main = putStrLn (calculateTime 50)


Но компиляция не завершилась, сообщив мне об ошибке:

app\Main.hs:18:18: error:
    * Couldn't match type `Int' with `[Char]'
      Expected type: String
        Actual type: Int
    * In the first argument of `putStrLn', namely `(calculateTime 50)'
      In the expression: putStrLn (calculateTime 50)
      In an equation for `main': main = putStrLn (calculateTime 50)
   |
18 | main = putStrLn (calculateTime 50)
   |                  ^^^^^^^^^^^^^^^^


--  While building package real-0.1.0.0 using:
      C:\sr\setup-exe-cache\x86_64-windows\Cabal-simple_Z6RU0evB_2.4.0.1_ghc-8.6.5.exe
--builddir=.stack-work\dist\e626a42b build lib:real exe:real-exe --ghc-options " -fdiagnostics-color=always"
    Process exited with code: ExitFailure 1



Насколько я понял, haskell ожидал, что функция заменится строкой, но фактически это
было число.

Я предполагал, что функция примет 1 аргумент (timeInS) типа Int (50) и отобразит
его на тип Int, исходя из этого объявления:

calculateTime :: Int -> Int


После чего напечатает отобразившееся значение:

putStrLn (calculateTime 50)


В итоге, я ожидал, что программа напечатает мне 178.

Где я допустил ошибку? И вообще, правильно ли я понял сообщение компилятора?
    


Ответы

Ответ 1



Ошибка в том, что putStrLn применяется только к значениям типа [Char] (он же String) putStrLn :: String -> IO () Нужно либо использовать show для преобразования числа в строку putStrLn (show (calculateTime 50)) Либо использовать print, который сделает ровно то же самое print (calculateTime 50)

Открыть из консоли вкладку с терминалом и вкладку с файлом в Vim 8

#консоль #vim


В Vim 8 добавили терминал, который вызывается командой :terminal. Вопрос: как из
командной строки вызвать vim, чтобы в первой вкладке сразу открылся терминал, а во
второй — файл? Что-то типа такого (не работает):

$ vim -p :terminal readme.txt

    


Ответы

Ответ 1



vim -c ':tab terminal' -c 'tabm 0' -p readme.txt После загрузки буфера, выполняется открытие новой вкладки с терминалом, перемещение текущей вкладки в начало. vim -c ':tab terminal' -c 'tabm 0' -c ':tabn' -p readme.txt Покажет содержимое файла, после загрузки.

Как использовать второй аргумент this в forEach?

#javascript #foreach


Всем привет.

Сегодня читая документацию реакта столкнулся с таким кодом

{React.Children.forEach(children, child => {
   console.log(child);
})}


Сначало подумал что это какой нибудь фокус Реакта потом узнал что нет это чистый JS.

То есть forEach принимает вторым аргументом this но абсолютно нигде нету про это
инфы посмотрел много где даже в  книге Дэвида Флэнагана JS подробное руководство .
Нашел очень мало ресурсов про this и то они говорят что он есть но как использовать
никто не сообщает.Learn.javascript.ru и то там только написано вот так:


  Второй, необязательный аргумент forEach позволяет указать контекст
  this для callback. Мы обсудим его в деталях чуть позже, сейчас он нам
  не важен.


Вот тут есть небольшая инфа.И конечно MDN.Но нигде нету пример с this

Очень хотел увидеть пример forEach с использованием this.Приветствуется  развернутые
ответы.
    


Ответы

Ответ 1



Достаточно надумано, но вот: function setStyle(entry) { // вот этот this привязывается через второй аргумент forEach this.style[entry[0]] = entry[1]; } let props = Object.entries({ color: 'red', fontSize: '30px' }); props.forEach(setStyle, d1); // устанавливаем все св-ва из объекта элементу d1 props.forEach(setStyle, d2); // устанавливаем все св-ва из объекта элементу d2
1
2


Группировка кол-ва выполненных задач по сотрудникам

#python #python_3x #pandas #dataframe #group_by


Как сгруппировать корректно данные? 

Имеется датафрейм со статусом завершенных заданий по каждому аналитику и типу задач:

df1

    ID     Board   Analyst   Status   Crea_d       Fin_d
    46258  RUCRA   Ivanov    open     2019-07-10    NaT
    2345   RUCRA   Ivanov    close    2019-07-11   2019-07-11
    46218  RUCRA   Ivanov    close    2019-07-11   2019-07-11
    3087   RUCRA   Sidorov   open     2019-07-22    NaT
    2367   BV      Petrov    open     2019-07-25    NaT
    2985   GRADE   Petrov    close    2019-07-05   2019-07-05 
    20987  GRADE   Ivanov    close    2019-07-11   2019-07-12
    2396   BV      Sidorov   open     2019-07-29     NaT


Необходимо сгруппировать данные таким образом, чтобы было видно сколько аналитик
выполнил и сколько еще невыполненных заданий по типам (Board) за определенный период
(за день, неделю, месяц).

grouped_df:

      Board   Analyst   Status   Count       
      RUCRA   Ivanov    open     1    
      RUCRA   Ivanov    close    2   
      RUCRA   Sidorov   open     1    
      BV      Petrov    open     1    
      GRADE   Petrov    close    1    
      GRADE   Ivanov    close    1
      BV      Sidorov   open     1     


Я что-то похожее сделал, но где-то нарушена логика, где не могу разобраться:

grouped_df: = (df1.groupby(['Board','Analyst','Status', pd.Grouper(key='Fin_d', freq='M')],
as_index=False)['ID'].count())


Просто дальше я хочу строить графики по каждому аналитику, сколько он по дням выполняет
заданий (bars) с трендовой линией, но то ли из-за ошибки в коде или нарушения логики,
ничего не выходит.
    


Ответы

Ответ 1



Если я правильно понял: In [5]: df1.groupby(["Board", "Analyst", "Status"]).size().reset_index(name="Count") Out[5]: Board Analyst Status Count 0 BV Petrov open 1 1 BV Sidorov open 1 2 GRADE Ivanov close 1 3 GRADE Petrov close 1 4 RUCRA Ivanov close 2 5 RUCRA Ivanov open 1 6 RUCRA Sidorov open 1 или так: In [11]: df1.groupby(["Board", "Analyst", "Status", pd.Grouper(key='Crea_d', freq='MS')]).size().reset_index(name="Count") Out[11]: Board Analyst Status Crea_d Count 0 BV Petrov open 2019-07-01 1 1 BV Sidorov open 2019-07-01 1 2 GRADE Ivanov close 2019-07-01 1 3 GRADE Petrov close 2019-07-01 1 4 RUCRA Ivanov close 2019-07-01 2 5 RUCRA Ivanov open 2019-07-01 1 6 RUCRA Sidorov open 2019-07-01 1

Как извлечь “скрытую” информацию из тегов с помощью Python и BeautifulSoup?

#python #парсер


Хочу сделать парсинг страниц Яндекс.Дзена, чтобы вытащить оттуда теги каждой публикации
и колчество прочитываний. Делаю это на Python с помощью BeautifulSoup.
При извлечение HTML кода страницы кодом

import urllib.request

from bs4 import BeautifulSoup

url = 'https://zen.yandex.ru/media/filmmaking/esli-vam-nravitsia-liucifer-posmotrite-i-eti-13-serialov-5d0f25adb34feb00af5df506'
response = urllib.request.urlopen(url)
page = BeautifulSoup(response, features="lxml")
print(page)


блоки, где находятся теги 



"теги"
и счетчик просмотров 13 тыс. дочитываний оказываются пустыми. Позволяет ли яндекс.дзен вообще достать эту информацию? Теми ли средствами я пользуюсь? В парсинге новичок)


Ответы

Ответ 1



Проблема в том, что BeautifulSoup не исполняет JS код, будь то отрисовывающий страницу или получающий данные из БД. Поэтому теги не заполнены, и данных внутри вы не видите. Используйте для этих целей Selenium, там точно все должно быть хорошо, так как запускается инстанс браузера, который точно отрендерит вам страничку и вернет полностью готовый html.

QtС++. Доработать поиск файлов в директории и поддиректориях

#cpp #алгоритм #qt #qt5 #поиск


Есть код:

 // Получение списка файлов в папке
    QStringList nameFilter;
        QDir dir(MTEPathTMP);
        nameFilter.clear();
        nameFilter << "*.png";

        QFileInfoList list = dir.entryInfoList( nameFilter, QDir::Files );
        QFileInfo fileinfo;

        nameFilter.clear();
        foreach (fileinfo, list) nameFilter << fileinfo.absoluteFilePath();


Он ищет файлы по маске в директории.

НО! Он не умеет смотреть в поддиректории. Как можно его доработать, чтоб он мог искать?
    


Ответы

Ответ 1



Уже обсуждалось тут. Я бы рекомендовал не изобретать велосипед с рекурсивной функцией, а применить готовый класс QDirIterator со специальным флагом в параметрах. QDirIterator it("/sys", QStringList() << "scaling_cur_freq", QDir::NoFilter, QDirIterator::Subdirectories); while (it.hasNext()) { QFile f(it.next()); f.open(QIODevice::ReadOnly); qDebug() << f.fileName() << f.readAll().trimmed().toDouble() / 1000 << "MHz"; }

Копия state в Redux

#reactjs #redux


До недавнего времени делал копию state с помощью выражения JSON.parse(JSON.stringify(state))
и не о чём не парился. Но узнал, что это неверный подход. Толкового объяснения не получил. 

Если это так, то почему?
    


Ответы

Ответ 1



Приходишь с девушкой в ресторан, просишь официанта вино. Тебе приносят кифир. Ну, пьется же? Безусловно, ваш способ работает, но бьет по глазу, так как приведение к строке. Кроме того, JSON.stringify() не сохраняет функции, помещенные в поля объекта. Это тоже не верное использование Redux, но всё же... Документация Redux предлагает использовать либо Object.assign(), function todoApp(state = initialState, action) { switch (action.type) { case SET_VISIBILITY_FILTER: return Object.assign({}, state) ... либо object spread syntax function todoApp(state = initialState, action) { switch (action.type) { case SET_VISIBILITY_FILTER: return { ...state } ...

Поиск “скрытой” подстроки в строке

#алгоритм #строки #поиск #подстрока


Надо узнать если ли в строке "раздробленная" подстрока.
Пример:

У нас имеется строка и предпологаемая подстрока, надо просто вывести true или false
если такая трока имеется
    


Ответы

Ответ 1



string a, b; cin >> a >> b; int bIndex=0; for (size_t i = 0; i < a.size(); i++) { if (b[bIndex] == a[i]) { bIndex++; } } if (bIndex==b.size()) { cout << "YES"; } else { cout << "NO"; }

Как получить значение из класса без методов

#javascript #классы


Как получить значение из класса без методов используя только конструктор
Пример кода -

class Value {
  constructor() {
    /*
    код который бы вернул число
    */
  }
}
let result = new Value();
console.log(result /*Выводит например 3*/);

    


Ответы

Ответ 1



Как-то так: class JobSeeker { i = -1; valueOf() { return this.i = this.i + 2; } } let inst = new JobSeeker(); console.log( inst == 1 && inst == 3 && inst == 5 );

Ответ 2



Можно вернуть либо ссылку на текущий объект, либо новый объект. Вернёт объект Value: class Value { constructor (name){ this.name = name; // Аналогично отработает без return return this.name; } } // Деструктуризация const {name} = new Value('Ivan'); console.log(name); Вернёт новый объект: class Value { constructor (name){ this.name = name; return {name}; } } const {name} = new Value('Ivan'); console.log(name); Примитив вернуть нельзя. Аналогичный вопрос.

Как вывести всплывающую подсказку при наведении курсора на регион карты?

#html #css #svg #css_animation


У меня есть, допустим, карта США. 





   
Необходимо при наведении курсора на определенный штат, окрасить его и вывести подсказку с информацией об этом штате. P.S Карта неполная, всего несколько штатов, так как есть ограничение - не больше 30.000 символов в сниппете


Ответы

Ответ 1



Для вывода подсказок можно применить тег SVG ... Если вы хотите реализовать вывод подсказки, например, какого-то участка карты, то необходимо обернуть path, который рисует этот участок групповым тегом . И разместить внутри него двойной тег с поясняющим текстом. Пример: <g> <title> "UT" - Utah State capital city - Salt Lake City Population City 186,440 Estimate Estimate (2018) 200,591
"ID" - IDAHO State capital city - Boise Population - 228,790 "UT" - Utah State capital city - Salt Lake City Population City 186,440 Estimate Estimate (2018) 200,591 "AZ" - Arizona State capital city - Phoenix Population City 1,445,632 Estimate Estimate (2018) 1,660,272 "NV" - Nevada State capital city - Carson City Population City 55,274 Estimate Estimate (2018) 55,414 "OR" - Oregon State capital city - Salem Population City 154,637 Estimate Estimate (2018) 173,442 "WA" - Washington Territory State capital city - Olympia Population City 46,478 Estimate (2018) 52,555 "CA" - California State capital city - Sacramento Population City 466,488 Estimate (2018) 508,529
Note: Если у вас не будет работать всплывающая подсказка, обязательно проверьте отсутствие стиля pointer-events:none; так как при этом происходит отключение событий мыши. Связанные вопросы: Как создать многострочный tooltip в SVG Как при наведении курсора на один из элементов SVG добиться, чтобы он поднялся выше других элементов

Какое отличие состояния от характеристики в Java?

#java #терминология


Какое отличие состояния от характеристики в Java?

Класс - некая абстракция, логическая структура, описывающая поведение и характеристики.


  Разве описывающая поведение и характеристики, разве не состояние?


Какое вообще отличие характеристики от состояния?
    


Ответы

Ответ 1



Характеристика это свойство, а состояние - конкретное значение этого свойства. Примеры: характеристика - состояние ----------------------------- скорость(м/с) - 10 цвет - зеленый масса(г) - 13 угол(радиан - 0.5

Трансформация DataFrame

#python #pandas #dataframe #group_by #статистика


Есть 2 pd.DataFrame:

a = pd.DataFrame([[1, 20], [2, 25], [3, 24], [1, 22], [2, 29]], columns=['type', 'size'])
b = pd.DataFrame([[1, 19], [1, 21], [2, 24], [4, 21]], columns=['type', 'size'])


В каждый DataFrame хочу добавить столбцы следующего типа

a['amount_mean_type'] = a['size'] / a.groupby('type')['size'].transform('mean')
a['amount_std_type'] = a['size'] / a.groupby('type')['size'].transform('std')


Вопрос в том, как мне сделать так, чтобы в b['amount_mean_type'] и b['amount_std_type']
я использовал mean и std по группам из a, а по тем категориям, которых нет в a, использовать
mean и std по всему сету (если это корректно). 

Что-то вроде этого: 

b['amount_mean_type'] = b['size'] / a.groupby('type')['size'].transform('mean')
b['amount_std_type'] = b['size'] / a.groupby('type')['size'].transform('std')


Но только с теми условиями, которые описал выше

UPD: пример фреймов на выходе

Для a все просто:

a['amount_mean_type'] = a['size'] / a.groupby('type')['size'].transform('mean')
a['amount_std_type'] = a['size'] / a.groupby('type')['size'].transform('std')

  type size amount_mean_type amount_std_type
0   1   20  0.952381    14.142136
1   2   25  0.925926    8.838835
2   3   24  1.000000    NaN 
3   1   22  1.047619    15.556349
4   2   29  1.074074    10.253048


для b приходится прописать вручную каждую операцию

b.loc[0, 'amount_mean_type'] = b.loc[0, 'size'] / a[a['type'] == 1]['size'].mean()
b.loc[1, 'amount_mean_type'] = b.loc[1, 'size'] / a[a['type'] == 1]['size'].mean()
b.loc[2, 'amount_mean_type'] = b.loc[2, 'size'] / a[a['type'] == 2]['size'].mean()
b.loc[3, 'amount_mean_type'] = b.loc[3, 'size'] / a['size'].mean()

b.loc[0, 'amount_std_type'] = b.loc[0, 'size'] / a[a['type'] == 1]['size'].std()
b.loc[1, 'amount_std_type'] = b.loc[1, 'size'] / a[a['type'] == 1]['size'].std()
b.loc[2, 'amount_std_type'] = b.loc[2, 'size'] / a[a['type'] == 2]['size'].std()
b.loc[3, 'amount_std_type'] = b.loc[3, 'size'] / a['size'].std()

  type size amount_mean_type amount_std_type
0   1   19  0.904762    13.435029
1   1   21  1.000000    14.849242
2   2   24  0.888889    8.485281
3   4   21  0.875000    6.192562 # Считается по всей переменной 'type', так как категории
(4) нет в `a`


Фреймы a и b можно рассматривать как train и test соответственно
    


Ответы

Ответ 1



tmp = a.groupby('type')['size'].agg(["mean", "std"]) res = (b.assign(x=b["type"].map(tmp["mean"]).fillna(a["size"].mean())) .eval("amount_mean_type = size / x") .drop(columns="x")) res = (res.assign(x=b["type"].map(tmp["std"]).fillna(a["size"].std())) .eval("amount_std_type = size / x") .drop(columns="x")) результат: In [28]: res Out[28]: type size amount_mean_type amount_std_type 0 1 19 0.904762 13.435029 1 1 21 1.000000 14.849242 2 2 24 0.888889 8.485281 3 4 21 0.875000 6.192562

Как пользоватся типом данных BOOLEAN в SELECT запросе?

#sql #oracle #plsql


Имеется PL/SQL функциия с типом данных BOOLEAN как параметр:

function get_something(name in varchar2, ignore_notfound in boolean);


Эта функция часть инструментов от сторонних разработчиков и я не могу её менять.

Хотелось  бы использовать эту функцию в SELECT запросе:

 select get_something('NAME', TRUE) from dual;


Но так не работает, получаю ошибку:


  ORA-00904: "TRUE": invalid identifier


Как понимаю, кючевое слово TRUE не распознаётся.

Как же сделать чтобы оно работало?
    


Ответы

Ответ 1



Можно сделать обёрточную функцию, например: function get_something (name in varchar2, ignore_notfound in varchar2) return varchar2 is begin return get_something (name, (upper(ignore_notfound) = 'TRUE')); end; Затем вызывать её так: select get_something ('Name', 'true') from dual; Решите, какие значения для ignore_notfound больше подходят. Я предположил, что 'TRUE' или 'true' означает TRUE, всё остальное - FALSE. Источник @TonyAndrews

Узнать имя jar файла, в котором запускатеся код

#java


есть jar файл w1.jar, нужно вывести в консоль его имя, имя файла может менятся, поэтому
нужен код, который определит название
    


Ответы

Ответ 1



В любом из методов класса, содержащего main String jarName = new File(getClass().getProtectionDomain() .getCodeSource() .getLocation() .toURI()).getName(); Или вместо getClass() можно написать конкретный класс, содержащий main.

Как удалить столбцы, у которых кол-во пропущенных значений больше 2 согласно прилагаемого алгоритма

#python #pandas #dataframe


Алгоритм удаления по заданию следующий:


найдите все такие столбцы (метод .isna() + подвыборка с условием)
определите их названия (поймите как выцепить названия и сохраните их в массив, т.е.
по цепочке примените методы .index, .tolist() или .values)
"дропните их" (используйте метод .drop (имена столбцов))
результат сохраните в новой табличке (например, data_1), исходную менять не нужно


Сделала по-другому:

cols_to_delete = df2.columns[df2.isna().sum() > 2]
df2.drop(cols_to_delete, axis = 1, inplace = True)


Что мне непонятно: как сделать задание по вышеуказанному алгоритму #1 - #4.

df = pd.DataFrame({
    'col1': [23, 54, pd.np.nan, 87],
    'col2': [45, 39, 45, 32],
    'col3': [pd.np.nan, pd.np.nan, 76, pd.np.nan,]
})

    


Ответы

Ответ 1



Исходный DF: In [92]: df Out[92]: col1 col2 col3 0 23.0 45 NaN 1 54.0 39 NaN 2 NaN 45 76.0 3 87.0 32 NaN Решение 1: In [93]: thresh = 2 In [94]: new = df.loc[:, df.isna().sum().le(thresh)] Решение 2: In [96]: new = df.drop(columns=df.columns[df.isna().sum() > thresh]) Результат: In [95]: new Out[95]: col1 col2 0 23.0 45 1 54.0 39 2 NaN 45 3 87.0 32

Как передать именованный аргумент sqlite?

#python #python_3x #sqlite #sqlite3


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

Создал базу данных следующим образом:

import sqlite3

conn = sqlite3.connect("mydatabase.db")
cursor = conn.cursor()

cursor.execute("CREATE TABLE users (id numeric)") #пробовал и текстовое значение


Пытался вставить переменную так:

ids = [] #заполненный список с значениями, которые мне нужно вставить
for i in ids:
   cursor.execute("INSERT INTO users VALUES (?,)", i) #пробовал через форматирование
строки, тоже не вышло


Что я делаю не так?
    


Ответы

Ответ 1



cursor.execute(sql, parameters) в качестве параметров ожидает итерируемый объект (обычно список или кортеж): ids = [1,2,3] for i in ids: cursor.execute("INSERT INTO users VALUES (?)", (i,)) # qmark style # NOTE: ----------------------------> ^^^ ^^^^ используем именованные параметры: for i in ids: cursor.execute("INSERT INTO users VALUES (:id)", {"id": i}) # (named style) ВНИМАНИЕ: (<скаляр>) - не является кортежем! In [55]: i = 1 In [56]: type( i ) Out[56]: int In [57]: type( (i) ) # / NOTE! Out[57]: int # \ (i) - это просто скаляр, а не кортеж In [58]: type( (i,) ) Out[58]: tuple

Проверить генерик-тип интерфейса в C#?

#c_sharp #net #рефлексия #net_core


У меня есть тип AType который реализует генерик-интерфейс IA
Тип BType реализует интерфейс IC.
Как я могу проверить связан AType с IC или нет?

class AType : IA
{}

class BType : IC
{}

interface IA
{ }

interface IC
{ }


Тип BType может быть любым и мне о нем ничего неизвестно. У меня есть экземпляр AType
и мне нужно понять реализует ли он IC через generic тип промежуточного интерфейса IA
Проверка ниже не работает: 

var aInstance = new AType();
aInstance is IA // false
...


Также для Type.IsAssignableFrom(Type)

typeof(IC).IsAssignableFrom(aInstance.GetType()) // false

    


Ответы

Ответ 1



Проверка ниже не работает: Верно, потому что компилятор ничего не знает о вариантности интерфейса. Если ваш интерфейс IA фактически является ковариантным, то укажите это явно: interface IA { } потом: var aInstance = new AType(); Console.WriteLine(aInstance is IA); // True Но явная вариантность — это ограничение и интерфейс может считаться ковариантным только в случае когда все его члены используют тип T только для возврата. Скомпилируется: interface IA { T Method(); } Не скомпилируется: interface IA { void Method(T t); } подробно: Вариативность в универсальных интерфейсах (C#) Если ваш тип не является ковариантным, то вам придется разбирать это явно. Для проверок внутри класса можно написать что-то вроде: class AType : IA { public bool HasParamenterOfTypeIC() { return typeof(IC).IsAssignableFrom(typeof(T)); } } тогда: var a = new AType(); Console.WriteLine(a.HasParamenterOfTypeIC()); // True var b = new AType(); Console.WriteLine(b.HasParamenterOfTypeIC()); // False для проверок снаружи вы должны еще и явно достать дженерик-параметр и проверить его на совместимость: class OType : IA { } class AType : IA { } class Program { static void Main() { Console.WriteLine(HasParamenterOfTypeIC(typeof(AType))); // True Console.WriteLine(HasParamenterOfTypeIC(typeof(OType))); // False } static bool HasParamenterOfTypeIC(Type type) { return type .GetInterfaces() .SelectMany(i => i.GetGenericArguments()) .Any(i => typeof(IC).IsAssignableFrom(i)); } }

Поиск и удаление строки с unicodeescape в mssql на python

#python #sql #python_3x #sql_server


В SQL таблице есть столбец sc_path, в котором содержится запись C:\Users\elebedev\Desktop\Python
Мне нужно удалить все строки в таблице содержащие эту запись.

from sqlalchemy import create_engine 


path=r'C:\Users\elebedev\Desktop\Python'

con_log = create_engine('mssql+pymssql://log:pass@s1c/base')
sql_log = "DELETE FROM python_log WHERE CONVERT(NVARCHAR, sc_path) = '{}' ".format(path)
with con_log.begin() as conn:
    conn.execute(sql_log)


Код выполняется, но он не видит эти строки. Как мне кажется, что это из за unicodeescape
символа, но это не точно. 

Подскажите, как быть? 
    


Ответы

Ответ 1



Вы используете raw string - соответственно Python сам "заэкранирует" обратные слеши: In [57]: path=r'C:\Users\elebedev\Desktop\Python' In [58]: path Out[58]: 'C:\\Users\\elebedev\\Desktop\\Python' Если вас интересуют строки, начинающиеся с данной подстроки, то запрос нужно изменить: sql_log = "DELETE FROM python_log WHERE CONVERT(NVARCHAR, sc_path) like CONVERT(NVARCHAR, %s)" parms = (f"{path}%", ) # NOTE: ^ ^ con_log.execute(sql_log, parms)

Ответ 2



Удалить как хотелось не получилось. Сделал чуток по другому. Но изначальным вариантом было бы интересней. from sqlalchemy import create_engine path='elebedev' con_log = create_engine('mssql+pymssql://login:passw@server/base') sql_log = "DELETE FROM python_log WHERE CONVERT(NVARCHAR, sc_path) like %s" parms = (f"%{path}%", ) # NOTE: ^ ^ ^ con_log.execute(sql_log, parms)

Есть ли смысл использовать собственные реализации базовых АТД в C++?

#cpp #алгоритм #типы_данных #функциональное_программирование #стандарт


Задался вопросом, имеет ли смысл в настоящее время использовать собственные реализации
таких типов данных как связный список/стек/очередь/словарь? Именно для выполнения реальных
задач, а не в учебных целях. Казалось бы, стандарт языка С++ на данный момент предоставляет
большое количество инструментов, но несмотря на это, в некоторых проектах всё ещё продолжают
использовать самописные реализации тех или иных АТД. В том редком случае, когда стандартные
средства уступают в производительности самописным, логично, что выбор вряд ли будет
в пользу стандартных. Но в большинстве случаев нет какой-либо критичной разницы между
двумя подходами. Так стоит ли игра свеч?
    


Ответы

Ответ 1



Реализация контейнеров и алгоритмов в STL или Boost - веселая штука. Их делают максимально унифицированными (в основном для покрытия максимального кол-ва задач) и очень тщательно проверяют на быстродействие и т.д. Их пишут не один десяток людей, а ревьювят его вообще все ). Это дает гарантию что конкретная реализация будет максимально удовлетворять потребностям большинства. Время когда люди писали свои "общие" контейнера и алгоритмы наверное прошло. Но во в задачах (пример: Вам нужен произвольный доступ, и ассоциотивность) - да надо писать свой костыль. В стандартах очень много ассемблерных вставок для оптимизации производительности, и поэтому я не думаю что компилятор родит более вменяемый код, чем тот над которым посидели оптимизаторы. ИМХО: В реальных задачах надо брать готовое, а не рожать что-то (ибо дорого) сейчас вообще большинство ничего не кодит (дешевле найти готовое и пришить), что разумеется пичалька

Ошибка:“ not all arguments converted during string formatting” [дубликат]

#python_3x


        
             
                
                    
                        
                            На этот вопрос уже даны ответы здесь:
                            
                        
                    
                
                        
                            Ошибка “not all arguments converted during string formatting”
[закрыт]
                                
                                    (2 ответа)
                                
                        
                                Закрыт 6 месяцев назад.
            
                    
Дано число a, например 923 451. Надо получить:

923451
92345
9234
923
92
9
0


Мой код:

q=(923451)
while int(q)>0:
    str(q)-str(q)%10
    print(q)


Ошибка:


  not all arguments converted during string formatting

    


Ответы

Ответ 1



Попробуйте так: a = int(input()) while a > 0: print(a) a = a // 10 print(0)

Неизвестный идентификатор в запросе из таблицы DUAL

#sql #oracle


select x from dual


этот запрос выдает ошибку:


  ORA-00904: "X": invalid identifier


Хорошо, понятно, идентификатор X у меня нигде не объявлен.

Но почему этот запрос выполняется нормально:

select n from dual


Что это за неизвестный но валидный идентификатор? Откуда он берется?

Также работает и запрос:

select q, y, s, d, n, m from dual




Воспроизводится в SQL*Plus:



PS Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit Production
    


Ответы

Ответ 1



DUAL это физическая таблица содержащая только одну колонку dummy и только одну запись со значением 'X'. Ни каких других колонок в ней не существует: SQL> select * from dual; DUMMY ----- X SQL> select n from dual; select n from dual * ERROR at line 1: ORA-00904: "N": invalid identifier Но в качестве столбца может быть указано любое действительное для листа запроса выражение. Например, для вызова функции без параметров скобоки не обязательны, и такое выражение ничем не отличается от колонки таблицы. Проверить наличие таковых по имени можно запросом: select owner, object_name, object_type from all_objects where object_name = 'N';

Переменная bool зависимая от значения float

#c_sharp


Нужно заиметь 2 переменные: флоат и бул.

И что бы при изменении Float, этот Bool был завязан на значения Float.

Выше некоторого уровня - true; 
Ниже некоторого уровня - false. 

Этот "некий уровень" должен задаватся в отдельной переменной. 

Не знаю как написать это правильно кодом.
    


Ответы

Ответ 1



Ужасающе плохо напианый вопрос. Но, думаю, я вопрос понял. Должно быть как-то так: float _floatZeroVal = 1.0f; public float FloatVal = 1.0f; public bool FloatIsLargerThanZero { get { return FloatVal > _floatZeroVal; } } в таком случае FloatVal и FloatIsLargerThanZero те переменные которые ты хотел.

Перегрузка оператора @ в Python

#python #python_3x #python_35 #перегрузка_операторов


Столкнулся с необходимостью перегрузки оператора @ в Python. Требуется чтобы объекты
класса M могли взаимодействовать друг с другом через оператор @.
Например: 

a = M()
b = M()
a @ b



требуемая сигнатура поведения.
Подскажите, какой магический метод отвечает за этот оператор. Заранее спасибо.

    


Ответы

Ответ 1



Для поддержки оператора @ нужно переопределить метод __matmul__ (Или __rmatmul__, если нужно реализовать ситуацию, когда слева от @ объект не поддерживающий оператор @, а справа объект нашего класса), для оператора @= - метод __imatmul__. Пример: class A: def __init__(self, x): self.x = x def __repr__(self): return 'A({})'.format(self.x) def __matmul__(self, other): print("Вызван метод __matmul__") if(isinstance(other, A)): return A(self.x * other.x) else: return A(self.x * other) def __rmatmul__(self, other): print("Вызван метод __rmatmul__") if(isinstance(other, A)): return A(self.x * other.x) else: return A(self.x * other) def __imatmul__(self, other): print("Вызван метод __imatmul__") return self @ other a2 = A(2) print(a2 @ A(3)) # Вывод: # Вызван метод __matmul__ # A(6) print(a2 @ 4) # Вывод: # Вызван метод __matmul__ # A(8) print(5 @ a2) # Вывод: # Вызван метод __rmatmul__ # A(10) a2 @= A(6) print(a2) # A(12) # Вывод: # Вызван метод __imatmul__ # Вызван метод __matmul__ # A(12) Документация: Emulating numeric types

Ответ 2



Он называется matmul: operator.matmul(a, b) operator.__matmul__(a, b) Return a @ b. Пример перекрытия: class M: def __matmul__(self, other): print(self, other) a = M() b = M() a @ b # <__main__.M object at 0x00000281C3A07860> <__main__.M object at 0x00000281C5935E10>

Удалить пустые элементы массива

#массивы #lua


Есть массив ITEMS(item1=1,item2=2,item4=4,"",item10=10,"",item16=16)

Вывожу его содержимое 
print("массив ITEMS:",table.concat (ITEMS, ", "))

Получаю: 
1, 2, 4, , 10, , 16

Как можно удалить пустые строки отсюда?
    


Ответы

Ответ 1



Ответ @Ainar-G работает некорректно для массивов, где два пустых элемента идут подряд. Есть два способа обойти это: Сперва записать элементы для удаления, а после уже удалить их: local a = { "a", "b", "", "c", "", "", "d" } local function cleanupArray(arr, valtodel) local todelete = {} for k, v in ipairs(arr) do if v == valtodel then todelete[#todelete+1] = k end end for k, v in ipairs(todelete) do table.remove(arr, v-k+1) end return arr end cleanupArray(a, "") print(table.concat(a, ", ")) Try it online! Не менять индекс, если мы удалили элемент: local a = { "a", "b", "", "c", "", "", "d" } local function cleanupArray(arr, valtodel) for i = 1, #arr do ::begin:: local v = arr[i] if v == nil then return end if v == valtodel then table.remove(arr, i) goto begin end end end cleanupArray(a, "") print(table.concat(a, ", "))